QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgsmarkersymbollayer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmarkersymbollayer.cpp
3  ---------------------
4  begin : November 2009
5  copyright : (C) 2009 by Martin Dobias
6  email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsmarkersymbollayer.h"
17 #include "qgssymbollayerutils.h"
18 
19 #include "qgsdxfexport.h"
20 #include "qgsdxfpaintdevice.h"
21 #include "qgsexpression.h"
22 #include "qgsfontutils.h"
23 #include "qgsimagecache.h"
24 #include "qgsimageoperation.h"
25 #include "qgsrendercontext.h"
26 #include "qgslogger.h"
27 #include "qgssvgcache.h"
28 #include "qgsunittypes.h"
29 #include "qgssymbol.h"
30 #include "qgsfillsymbol.h"
31 
32 #include <QPainter>
33 #include <QSvgRenderer>
34 #include <QFileInfo>
35 #include <QDir>
36 #include <QDomDocument>
37 #include <QDomElement>
38 
39 #include <cmath>
40 
41 Q_GUI_EXPORT extern int qt_defaultDpiX();
42 Q_GUI_EXPORT extern int qt_defaultDpiY();
43 
44 static constexpr int MAX_FONT_CHARACTER_SIZE_IN_PIXELS = 500;
45 
46 static void _fixQPictureDPI( QPainter *p )
47 {
48  // QPicture makes an assumption that we drawing to it with system DPI.
49  // Then when being drawn, it scales the painter. The following call
50  // negates the effect. There is no way of setting QPicture's DPI.
51  // See QTBUG-20361
52  p->scale( static_cast< double >( qt_defaultDpiX() ) / p->device()->logicalDpiX(),
53  static_cast< double >( qt_defaultDpiY() ) / p->device()->logicalDpiY() );
54 }
55 
56 
58 
59 
60 //
61 // QgsSimpleMarkerSymbolLayerBase
62 //
63 
65 {
66  QList< Qgis::MarkerShape > shapes;
96 
97  return shapes;
98 }
99 
101  : mShape( shape )
102 {
103  mSize = size;
104  mAngle = angle;
105  mOffset = QPointF( 0, 0 );
109 }
110 
112 
114 {
115  switch ( shape )
116  {
139  return true;
140 
148  return false;
149  }
150  return true;
151 }
152 
154 {
155  const bool hasDataDefinedRotation = context.renderHints() & Qgis::SymbolRenderHint::DynamicRotation
157  const bool hasDataDefinedSize = mDataDefinedProperties.isActive( QgsSymbolLayer::PropertySize );
158 
159  // use either QPolygonF or QPainterPath for drawing
160  if ( !prepareMarkerShape( mShape ) ) // drawing as a polygon
161  {
162  prepareMarkerPath( mShape ); // drawing as a painter path
163  }
164 
165  QTransform transform;
166 
167  // scale the shape (if the size is not going to be modified)
168  if ( !hasDataDefinedSize )
169  {
170  double scaledSize = context.renderContext().convertToPainterUnits( mSize, mSizeUnit, mSizeMapUnitScale );
172  {
173  // rendering for symbol previews -- an size in meters in map units can't be calculated, so treat the size as millimeters
174  // and clamp it to a reasonable range. It's the best we can do in this situation!
175  scaledSize = std::min( std::max( context.renderContext().convertToPainterUnits( mSize, QgsUnitTypes::RenderMillimeters ), 3.0 ), 100.0 );
176  }
177 
178  const double half = scaledSize / 2.0;
179  transform.scale( half, half );
180  }
181 
182  // rotate if the rotation is not going to be changed during the rendering
183  if ( !hasDataDefinedRotation && !qgsDoubleNear( mAngle, 0.0 ) )
184  {
185  transform.rotate( mAngle );
186  }
187 
188  if ( !mPolygon.isEmpty() )
189  mPolygon = transform.map( mPolygon );
190  else
191  mPath = transform.map( mPath );
192 
194 }
195 
197 {
198  Q_UNUSED( context )
199 }
200 
202 {
203  //making changes here? Don't forget to also update ::bounds if the changes affect the bounding box
204  //of the rendered point!
205 
206  QPainter *p = context.renderContext().painter();
207  if ( !p )
208  {
209  return;
210  }
211 
212  bool hasDataDefinedSize = false;
213  const double scaledSize = calculateSize( context, hasDataDefinedSize );
214 
215  bool hasDataDefinedRotation = false;
216  QPointF offset;
217  double angle = 0;
218  calculateOffsetAndRotation( context, scaledSize, hasDataDefinedRotation, offset, angle );
219 
220  //data defined shape?
221  bool createdNewPath = false;
222  bool ok = true;
223  Qgis::MarkerShape symbol = mShape;
225  {
226  context.setOriginalValueVariable( encodeShape( symbol ) );
228  if ( !exprVal.isNull() )
229  {
230  const Qgis::MarkerShape decoded = decodeShape( exprVal.toString(), &ok );
231  if ( ok )
232  {
233  symbol = decoded;
234 
235  if ( !prepareMarkerShape( symbol ) ) // drawing as a polygon
236  {
237  prepareMarkerPath( symbol ); // drawing as a painter path
238  }
239  createdNewPath = true;
240  }
241  }
242  else
243  {
244  symbol = mShape;
245  }
246  }
247 
248  QTransform transform;
249 
250  // move to the desired position
251  transform.translate( point.x() + offset.x(), point.y() + offset.y() );
252 
253  // resize if necessary
254  if ( hasDataDefinedSize || createdNewPath )
255  {
256  double s = context.renderContext().convertToPainterUnits( scaledSize, mSizeUnit, mSizeMapUnitScale );
258  {
259  // rendering for symbol previews -- a size in meters in map units can't be calculated, so treat the size as millimeters
260  // and clamp it to a reasonable range. It's the best we can do in this situation!
261  s = std::min( std::max( context.renderContext().convertToPainterUnits( mSize, QgsUnitTypes::RenderMillimeters ), 3.0 ), 100.0 );
262  }
263  const double half = s / 2.0;
264  transform.scale( half, half );
265  }
266 
267  if ( !qgsDoubleNear( angle, 0.0 ) && ( hasDataDefinedRotation || createdNewPath ) )
268  {
269  transform.rotate( angle );
270  }
271 
272  //need to pass: symbol, polygon, path
273 
274  QPolygonF polygon;
275  QPainterPath path;
276  if ( !mPolygon.isEmpty() )
277  {
278  polygon = transform.map( mPolygon );
279  }
280  else
281  {
282  path = transform.map( mPath );
283  }
284  draw( context, symbol, polygon, path );
285 }
286 
288 {
289  bool hasDataDefinedSize = false;
290  double scaledSize = calculateSize( context, hasDataDefinedSize );
291 
292  bool hasDataDefinedRotation = false;
293  QPointF offset;
294  double angle = 0;
295  calculateOffsetAndRotation( context, scaledSize, hasDataDefinedRotation, offset, angle );
296 
297  scaledSize = context.renderContext().convertToPainterUnits( scaledSize, mSizeUnit, mSizeMapUnitScale );
298 
299  QTransform transform;
300 
301  // move to the desired position
302  transform.translate( point.x() + offset.x(), point.y() + offset.y() );
303 
304  if ( !qgsDoubleNear( angle, 0.0 ) )
305  transform.rotate( angle );
306 
307  return transform.mapRect( QRectF( -scaledSize / 2.0,
308  -scaledSize / 2.0,
309  scaledSize,
310  scaledSize ) );
311 }
312 
314 {
315  if ( ok )
316  *ok = true;
317  const QString cleaned = name.toLower().trimmed();
318 
319  if ( cleaned == QLatin1String( "square" ) || cleaned == QLatin1String( "rectangle" ) )
321  else if ( cleaned == QLatin1String( "square_with_corners" ) )
323  else if ( cleaned == QLatin1String( "diamond" ) )
325  else if ( cleaned == QLatin1String( "pentagon" ) )
327  else if ( cleaned == QLatin1String( "hexagon" ) )
329  else if ( cleaned == QLatin1String( "octagon" ) )
331  else if ( cleaned == QLatin1String( "triangle" ) )
333  else if ( cleaned == QLatin1String( "equilateral_triangle" ) )
335  else if ( cleaned == QLatin1String( "star" ) || cleaned == QLatin1String( "regular_star" ) )
337  else if ( cleaned == QLatin1String( "arrow" ) )
339  else if ( cleaned == QLatin1String( "circle" ) )
341  else if ( cleaned == QLatin1String( "cross" ) )
343  else if ( cleaned == QLatin1String( "cross_fill" ) )
345  else if ( cleaned == QLatin1String( "cross2" ) || cleaned == QLatin1String( "x" ) )
347  else if ( cleaned == QLatin1String( "line" ) )
349  else if ( cleaned == QLatin1String( "arrowhead" ) )
351  else if ( cleaned == QLatin1String( "filled_arrowhead" ) )
353  else if ( cleaned == QLatin1String( "semi_circle" ) )
355  else if ( cleaned == QLatin1String( "third_circle" ) )
357  else if ( cleaned == QLatin1String( "quarter_circle" ) )
359  else if ( cleaned == QLatin1String( "quarter_square" ) )
361  else if ( cleaned == QLatin1String( "half_square" ) )
363  else if ( cleaned == QLatin1String( "diagonal_half_square" ) )
365  else if ( cleaned == QLatin1String( "right_half_triangle" ) )
367  else if ( cleaned == QLatin1String( "left_half_triangle" ) )
369  else if ( cleaned == QLatin1String( "asterisk_fill" ) )
371  else if ( cleaned == QLatin1String( "half_arc" ) )
373  else if ( cleaned == QLatin1String( "third_arc" ) )
375  else if ( cleaned == QLatin1String( "quarter_arc" ) )
377 
378  if ( ok )
379  *ok = false;
381 }
382 
384 {
385  switch ( shape )
386  {
388  return QStringLiteral( "square" );
390  return QStringLiteral( "quarter_square" );
392  return QStringLiteral( "half_square" );
394  return QStringLiteral( "diagonal_half_square" );
396  return QStringLiteral( "diamond" );
398  return QStringLiteral( "pentagon" );
400  return QStringLiteral( "hexagon" );
402  return QStringLiteral( "octagon" );
404  return QStringLiteral( "square_with_corners" );
406  return QStringLiteral( "triangle" );
408  return QStringLiteral( "equilateral_triangle" );
410  return QStringLiteral( "left_half_triangle" );
412  return QStringLiteral( "right_half_triangle" );
414  return QStringLiteral( "star" );
416  return QStringLiteral( "arrow" );
418  return QStringLiteral( "filled_arrowhead" );
420  return QStringLiteral( "cross_fill" );
422  return QStringLiteral( "circle" );
424  return QStringLiteral( "cross" );
426  return QStringLiteral( "cross2" );
428  return QStringLiteral( "line" );
430  return QStringLiteral( "arrowhead" );
432  return QStringLiteral( "semi_circle" );
434  return QStringLiteral( "third_circle" );
436  return QStringLiteral( "quarter_circle" );
438  return QStringLiteral( "asterisk_fill" );
440  return QStringLiteral( "half_arc" );
442  return QStringLiteral( "third_arc" );
444  return QStringLiteral( "quarter_arc" );
445  }
446  return QString();
447 }
448 
450 {
451  return shapeToPolygon( shape, mPolygon );
452 }
453 
455 {
456  polygon.clear();
457 
458  switch ( shape )
459  {
461  polygon = QPolygonF( QRectF( QPointF( -1, -1 ), QPointF( 1, 1 ) ) );
462  return true;
463 
465  {
466  static constexpr double VERTEX_OFFSET_FROM_ORIGIN = 0.6072;
467 
468  polygon << QPointF( - VERTEX_OFFSET_FROM_ORIGIN, 1 )
469  << QPointF( VERTEX_OFFSET_FROM_ORIGIN, 1 )
470  << QPointF( 1, VERTEX_OFFSET_FROM_ORIGIN )
471  << QPointF( 1, -VERTEX_OFFSET_FROM_ORIGIN )
472  << QPointF( VERTEX_OFFSET_FROM_ORIGIN, -1 )
473  << QPointF( -VERTEX_OFFSET_FROM_ORIGIN, -1 )
474  << QPointF( -1, -VERTEX_OFFSET_FROM_ORIGIN )
475  << QPointF( -1, VERTEX_OFFSET_FROM_ORIGIN )
476  << QPointF( -VERTEX_OFFSET_FROM_ORIGIN, 1 );
477  return true;
478  }
479 
481  polygon = QPolygonF( QRectF( QPointF( -1, -1 ), QPointF( 0, 0 ) ) );
482  return true;
483 
485  polygon = QPolygonF( QRectF( QPointF( -1, -1 ), QPointF( 0, 1 ) ) );
486  return true;
487 
489  polygon << QPointF( -1, -1 ) << QPointF( 1, 1 ) << QPointF( -1, 1 ) << QPointF( -1, -1 );
490  return true;
491 
493  polygon << QPointF( -1, 0 ) << QPointF( 0, 1 )
494  << QPointF( 1, 0 ) << QPointF( 0, -1 ) << QPointF( -1, 0 );
495  return true;
496 
498  /* angular-representation of hardcoded values used
499  polygon << QPointF( std::sin( DEG2RAD( 288.0 ) ), - std::cos( DEG2RAD( 288.0 ) ) )
500  << QPointF( std::sin( DEG2RAD( 216.0 ) ), - std::cos( DEG2RAD( 216.0 ) ) )
501  << QPointF( std::sin( DEG2RAD( 144.0 ) ), - std::cos( DEG2RAD( 144.0 ) ) )
502  << QPointF( std::sin( DEG2RAD( 72.0 ) ), - std::cos( DEG2RAD( 72.0 ) ) )
503  << QPointF( 0, -1 ); */
504  polygon << QPointF( -0.9511, -0.3090 )
505  << QPointF( -0.5878, 0.8090 )
506  << QPointF( 0.5878, 0.8090 )
507  << QPointF( 0.9511, -0.3090 )
508  << QPointF( 0, -1 )
509  << QPointF( -0.9511, -0.3090 );
510  return true;
511 
513  /* angular-representation of hardcoded values used
514  polygon << QPointF( std::sin( DEG2RAD( 300.0 ) ), - std::cos( DEG2RAD( 300.0 ) ) )
515  << QPointF( std::sin( DEG2RAD( 240.0 ) ), - std::cos( DEG2RAD( 240.0 ) ) )
516  << QPointF( std::sin( DEG2RAD( 180.0 ) ), - std::cos( DEG2RAD( 180.0 ) ) )
517  << QPointF( std::sin( DEG2RAD( 120.0 ) ), - std::cos( DEG2RAD( 120.0 ) ) )
518  << QPointF( std::sin( DEG2RAD( 60.0 ) ), - std::cos( DEG2RAD( 60.0 ) ) )
519  << QPointF( 0, -1 ); */
520  polygon << QPointF( -0.8660, -0.5 )
521  << QPointF( -0.8660, 0.5 )
522  << QPointF( 0, 1 )
523  << QPointF( 0.8660, 0.5 )
524  << QPointF( 0.8660, -0.5 )
525  << QPointF( 0, -1 )
526  << QPointF( -0.8660, -0.5 );
527  return true;
528 
530  {
531  static constexpr double VERTEX_OFFSET_FROM_ORIGIN = 1.0 / ( 1 + M_SQRT2 );
532 
533  polygon << QPointF( - VERTEX_OFFSET_FROM_ORIGIN, 1 )
534  << QPointF( VERTEX_OFFSET_FROM_ORIGIN, 1 )
535  << QPointF( 1, VERTEX_OFFSET_FROM_ORIGIN )
536  << QPointF( 1, -VERTEX_OFFSET_FROM_ORIGIN )
537  << QPointF( VERTEX_OFFSET_FROM_ORIGIN, -1 )
538  << QPointF( -VERTEX_OFFSET_FROM_ORIGIN, -1 )
539  << QPointF( -1, -VERTEX_OFFSET_FROM_ORIGIN )
540  << QPointF( -1, VERTEX_OFFSET_FROM_ORIGIN )
541  << QPointF( -VERTEX_OFFSET_FROM_ORIGIN, 1 );
542  return true;
543  }
544 
546  polygon << QPointF( -1, 1 ) << QPointF( 1, 1 ) << QPointF( 0, -1 ) << QPointF( -1, 1 );
547  return true;
548 
550  /* angular-representation of hardcoded values used
551  polygon << QPointF( std::sin( DEG2RAD( 240.0 ) ), - std::cos( DEG2RAD( 240.0 ) ) )
552  << QPointF( std::sin( DEG2RAD( 120.0 ) ), - std::cos( DEG2RAD( 120.0 ) ) )
553  << QPointF( 0, -1 ); */
554  polygon << QPointF( -0.8660, 0.5 )
555  << QPointF( 0.8660, 0.5 )
556  << QPointF( 0, -1 )
557  << QPointF( -0.8660, 0.5 );
558  return true;
559 
561  polygon << QPointF( 0, 1 ) << QPointF( 1, 1 ) << QPointF( 0, -1 ) << QPointF( 0, 1 );
562  return true;
563 
565  polygon << QPointF( -1, 1 ) << QPointF( 0, 1 ) << QPointF( 0, -1 ) << QPointF( -1, 1 );
566  return true;
567 
569  {
570  const double inner_r = std::cos( DEG2RAD( 72.0 ) ) / std::cos( DEG2RAD( 36.0 ) );
571 
572  polygon << QPointF( inner_r * std::sin( DEG2RAD( 324.0 ) ), - inner_r * std::cos( DEG2RAD( 324.0 ) ) ) // 324
573  << QPointF( std::sin( DEG2RAD( 288.0 ) ), - std::cos( DEG2RAD( 288 ) ) ) // 288
574  << QPointF( inner_r * std::sin( DEG2RAD( 252.0 ) ), - inner_r * std::cos( DEG2RAD( 252.0 ) ) ) // 252
575  << QPointF( std::sin( DEG2RAD( 216.0 ) ), - std::cos( DEG2RAD( 216.0 ) ) ) // 216
576  << QPointF( 0, inner_r ) // 180
577  << QPointF( std::sin( DEG2RAD( 144.0 ) ), - std::cos( DEG2RAD( 144.0 ) ) ) // 144
578  << QPointF( inner_r * std::sin( DEG2RAD( 108.0 ) ), - inner_r * std::cos( DEG2RAD( 108.0 ) ) ) // 108
579  << QPointF( std::sin( DEG2RAD( 72.0 ) ), - std::cos( DEG2RAD( 72.0 ) ) ) // 72
580  << QPointF( inner_r * std::sin( DEG2RAD( 36.0 ) ), - inner_r * std::cos( DEG2RAD( 36.0 ) ) ) // 36
581  << QPointF( 0, -1 )
582  << QPointF( inner_r * std::sin( DEG2RAD( 324.0 ) ), - inner_r * std::cos( DEG2RAD( 324.0 ) ) ); // 324; // 0
583  return true;
584  }
585 
587  polygon << QPointF( 0, -1 )
588  << QPointF( 0.5, -0.5 )
589  << QPointF( 0.25, -0.5 )
590  << QPointF( 0.25, 1 )
591  << QPointF( -0.25, 1 )
592  << QPointF( -0.25, -0.5 )
593  << QPointF( -0.5, -0.5 )
594  << QPointF( 0, -1 );
595  return true;
596 
598  polygon << QPointF( 0, 0 ) << QPointF( -1, 1 ) << QPointF( -1, -1 ) << QPointF( 0, 0 );
599  return true;
600 
602  polygon << QPointF( -1, -0.2 )
603  << QPointF( -1, -0.2 )
604  << QPointF( -1, 0.2 )
605  << QPointF( -0.2, 0.2 )
606  << QPointF( -0.2, 1 )
607  << QPointF( 0.2, 1 )
608  << QPointF( 0.2, 0.2 )
609  << QPointF( 1, 0.2 )
610  << QPointF( 1, -0.2 )
611  << QPointF( 0.2, -0.2 )
612  << QPointF( 0.2, -1 )
613  << QPointF( -0.2, -1 )
614  << QPointF( -0.2, -0.2 )
615  << QPointF( -1, -0.2 );
616  return true;
617 
619  {
620  static constexpr double THICKNESS = 0.3;
621  static constexpr double HALF_THICKNESS = THICKNESS / 2.0;
622  static constexpr double INTERSECTION_POINT = THICKNESS / M_SQRT2;
623  static constexpr double DIAGONAL1 = M_SQRT1_2 - INTERSECTION_POINT * 0.5;
624  static constexpr double DIAGONAL2 = M_SQRT1_2 + INTERSECTION_POINT * 0.5;
625 
626  polygon << QPointF( -HALF_THICKNESS, -1 )
627  << QPointF( HALF_THICKNESS, -1 )
628  << QPointF( HALF_THICKNESS, -HALF_THICKNESS - INTERSECTION_POINT )
629  << QPointF( DIAGONAL1, -DIAGONAL2 )
630  << QPointF( DIAGONAL2, -DIAGONAL1 )
631  << QPointF( HALF_THICKNESS + INTERSECTION_POINT, -HALF_THICKNESS )
632  << QPointF( 1, -HALF_THICKNESS )
633  << QPointF( 1, HALF_THICKNESS )
634  << QPointF( HALF_THICKNESS + INTERSECTION_POINT, HALF_THICKNESS )
635  << QPointF( DIAGONAL2, DIAGONAL1 )
636  << QPointF( DIAGONAL1, DIAGONAL2 )
637  << QPointF( HALF_THICKNESS, HALF_THICKNESS + INTERSECTION_POINT )
638  << QPointF( HALF_THICKNESS, 1 )
639  << QPointF( -HALF_THICKNESS, 1 )
640  << QPointF( -HALF_THICKNESS, HALF_THICKNESS + INTERSECTION_POINT )
641  << QPointF( -DIAGONAL1, DIAGONAL2 )
642  << QPointF( -DIAGONAL2, DIAGONAL1 )
643  << QPointF( -HALF_THICKNESS - INTERSECTION_POINT, HALF_THICKNESS )
644  << QPointF( -1, HALF_THICKNESS )
645  << QPointF( -1, -HALF_THICKNESS )
646  << QPointF( -HALF_THICKNESS - INTERSECTION_POINT, -HALF_THICKNESS )
647  << QPointF( -DIAGONAL2, -DIAGONAL1 )
648  << QPointF( -DIAGONAL1, -DIAGONAL2 )
649  << QPointF( -HALF_THICKNESS, -HALF_THICKNESS - INTERSECTION_POINT )
650  << QPointF( -HALF_THICKNESS, -1 );
651  return true;
652  }
653 
665  return false;
666  }
667 
668  return false;
669 }
670 
672 {
673  mPath = QPainterPath();
674 
675  switch ( symbol )
676  {
678 
679  mPath.addEllipse( QRectF( -1, -1, 2, 2 ) ); // x,y,w,h
680  return true;
681 
683  mPath.arcTo( -1, -1, 2, 2, 0, 180 );
684  mPath.lineTo( 0, 0 );
685  return true;
686 
688  mPath.arcTo( -1, -1, 2, 2, 90, 120 );
689  mPath.lineTo( 0, 0 );
690  return true;
691 
693  mPath.arcTo( -1, -1, 2, 2, 90, 90 );
694  mPath.lineTo( 0, 0 );
695  return true;
696 
698  mPath.moveTo( 1, 0 );
699  mPath.arcTo( -1, -1, 2, 2, 0, 180 );
700  return true;
701 
703  mPath.moveTo( 0, -1 );
704  mPath.arcTo( -1, -1, 2, 2, 90, 120 );
705  return true;
706 
708  mPath.moveTo( 0, -1 );
709  mPath.arcTo( -1, -1, 2, 2, 90, 90 );
710  return true;
711 
713  mPath.moveTo( -1, 0 );
714  mPath.lineTo( 1, 0 ); // horizontal
715  mPath.moveTo( 0, -1 );
716  mPath.lineTo( 0, 1 ); // vertical
717  return true;
718 
720  mPath.moveTo( -1, -1 );
721  mPath.lineTo( 1, 1 );
722  mPath.moveTo( 1, -1 );
723  mPath.lineTo( -1, 1 );
724  return true;
725 
727  mPath.moveTo( 0, -1 );
728  mPath.lineTo( 0, 1 ); // vertical line
729  return true;
730 
732  mPath.moveTo( -1, -1 );
733  mPath.lineTo( 0, 0 );
734  mPath.lineTo( -1, 1 );
735  return true;
736 
755  return false;
756  }
757  return false;
758 }
759 
760 double QgsSimpleMarkerSymbolLayerBase::calculateSize( QgsSymbolRenderContext &context, bool &hasDataDefinedSize ) const
761 {
762  double scaledSize = mSize;
763 
765  bool ok = true;
766  if ( hasDataDefinedSize )
767  {
768  context.setOriginalValueVariable( mSize );
770  mSize, &ok );
771  }
772 
773  if ( hasDataDefinedSize && ok )
774  {
775  switch ( mScaleMethod )
776  {
778  scaledSize = std::sqrt( scaledSize );
779  break;
781  break;
782  }
783  }
784 
785  return scaledSize;
786 }
787 
788 void QgsSimpleMarkerSymbolLayerBase::calculateOffsetAndRotation( QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedRotation, QPointF &offset, double &angle ) const
789 {
790  //offset
791  double offsetX = 0;
792  double offsetY = 0;
793  markerOffset( context, scaledSize, scaledSize, offsetX, offsetY );
794  offset = QPointF( offsetX, offsetY );
795 
796  hasDataDefinedRotation = false;
797  //angle
798  bool ok = true;
799  angle = mAngle + mLineAngle;
801  {
802  context.setOriginalValueVariable( angle );
804 
805  // If the expression evaluation was not successful, fallback to static value
806  if ( !ok )
807  angle = mAngle + mLineAngle;
808 
809  hasDataDefinedRotation = true;
810  }
811 
812  hasDataDefinedRotation = context.renderHints() & Qgis::SymbolRenderHint::DynamicRotation || hasDataDefinedRotation;
813 
814  if ( hasDataDefinedRotation )
815  {
816  // For non-point markers, "dataDefinedRotation" means following the
817  // shape (shape-data defined). For them, "field-data defined" does
818  // not work at all. TODO: if "field-data defined" ever gets implemented
819  // we'll need a way to distinguish here between the two, possibly
820  // using another flag in renderHints()
821  const QgsFeature *f = context.feature();
822  if ( f )
823  {
824  if ( f->hasGeometry() && f->geometry().type() == QgsWkbTypes::PointGeometry )
825  {
826  const QgsMapToPixel &m2p = context.renderContext().mapToPixel();
827  angle += m2p.mapRotation();
828  }
829  }
830  }
831 
832  if ( angle )
834 }
835 
836 
837 //
838 // QgsSimpleMarkerSymbolLayer
839 //
840 
841 QgsSimpleMarkerSymbolLayer::QgsSimpleMarkerSymbolLayer( Qgis::MarkerShape shape, double size, double angle, Qgis::ScaleMethod scaleMethod, const QColor &color, const QColor &strokeColor, Qt::PenJoinStyle penJoinStyle )
842  : QgsSimpleMarkerSymbolLayerBase( shape, size, angle, scaleMethod )
843  , mStrokeColor( strokeColor )
844  , mPenJoinStyle( penJoinStyle )
845 {
846  mColor = color;
847 }
848 
850 
852 {
856  Qt::PenJoinStyle penJoinStyle = DEFAULT_SIMPLEMARKER_JOINSTYLE;
860 
861  if ( props.contains( QStringLiteral( "name" ) ) )
862  {
863  shape = decodeShape( props[QStringLiteral( "name" )].toString() );
864  }
865  if ( props.contains( QStringLiteral( "color" ) ) )
866  color = QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "color" )].toString() );
867  if ( props.contains( QStringLiteral( "color_border" ) ) )
868  {
869  //pre 2.5 projects use "color_border"
870  strokeColor = QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "color_border" )].toString() );
871  }
872  else if ( props.contains( QStringLiteral( "outline_color" ) ) )
873  {
874  strokeColor = QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "outline_color" )].toString() );
875  }
876  else if ( props.contains( QStringLiteral( "line_color" ) ) )
877  {
878  strokeColor = QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "line_color" )].toString() );
879  }
880  if ( props.contains( QStringLiteral( "joinstyle" ) ) )
881  {
882  penJoinStyle = QgsSymbolLayerUtils::decodePenJoinStyle( props[QStringLiteral( "joinstyle" )].toString() );
883  }
884  if ( props.contains( QStringLiteral( "size" ) ) )
885  size = props[QStringLiteral( "size" )].toDouble();
886  if ( props.contains( QStringLiteral( "angle" ) ) )
887  angle = props[QStringLiteral( "angle" )].toDouble();
888  if ( props.contains( QStringLiteral( "scale_method" ) ) )
889  scaleMethod = QgsSymbolLayerUtils::decodeScaleMethod( props[QStringLiteral( "scale_method" )].toString() );
890 
892  if ( props.contains( QStringLiteral( "offset" ) ) )
893  m->setOffset( QgsSymbolLayerUtils::decodePoint( props[QStringLiteral( "offset" )].toString() ) );
894  if ( props.contains( QStringLiteral( "offset_unit" ) ) )
895  m->setOffsetUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "offset_unit" )].toString() ) );
896  if ( props.contains( QStringLiteral( "offset_map_unit_scale" ) ) )
897  m->setOffsetMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "offset_map_unit_scale" )].toString() ) );
898  if ( props.contains( QStringLiteral( "size_unit" ) ) )
899  m->setSizeUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "size_unit" )].toString() ) );
900  if ( props.contains( QStringLiteral( "size_map_unit_scale" ) ) )
901  m->setSizeMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "size_map_unit_scale" )].toString() ) );
902 
903  if ( props.contains( QStringLiteral( "outline_style" ) ) )
904  {
905  m->setStrokeStyle( QgsSymbolLayerUtils::decodePenStyle( props[QStringLiteral( "outline_style" )].toString() ) );
906  }
907  else if ( props.contains( QStringLiteral( "line_style" ) ) )
908  {
909  m->setStrokeStyle( QgsSymbolLayerUtils::decodePenStyle( props[QStringLiteral( "line_style" )].toString() ) );
910  }
911  if ( props.contains( QStringLiteral( "outline_width" ) ) )
912  {
913  m->setStrokeWidth( props[QStringLiteral( "outline_width" )].toDouble() );
914  }
915  else if ( props.contains( QStringLiteral( "line_width" ) ) )
916  {
917  m->setStrokeWidth( props[QStringLiteral( "line_width" )].toDouble() );
918  }
919  if ( props.contains( QStringLiteral( "outline_width_unit" ) ) )
920  {
921  m->setStrokeWidthUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "outline_width_unit" )].toString() ) );
922  }
923  if ( props.contains( QStringLiteral( "line_width_unit" ) ) )
924  {
925  m->setStrokeWidthUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "line_width_unit" )].toString() ) );
926  }
927  if ( props.contains( QStringLiteral( "outline_width_map_unit_scale" ) ) )
928  {
929  m->setStrokeWidthMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "outline_width_map_unit_scale" )].toString() ) );
930  }
931 
932  if ( props.contains( QStringLiteral( "horizontal_anchor_point" ) ) )
933  {
934  m->setHorizontalAnchorPoint( QgsMarkerSymbolLayer::HorizontalAnchorPoint( props[ QStringLiteral( "horizontal_anchor_point" )].toInt() ) );
935  }
936  if ( props.contains( QStringLiteral( "vertical_anchor_point" ) ) )
937  {
938  m->setVerticalAnchorPoint( QgsMarkerSymbolLayer::VerticalAnchorPoint( props[ QStringLiteral( "vertical_anchor_point" )].toInt() ) );
939  }
940 
941  if ( props.contains( QStringLiteral( "cap_style" ) ) )
942  {
943  m->setPenCapStyle( QgsSymbolLayerUtils::decodePenCapStyle( props[QStringLiteral( "cap_style" )].toString() ) );
944  }
945 
947 
948  return m;
949 }
950 
951 
953 {
954  return QStringLiteral( "SimpleMarker" );
955 }
956 
958 {
960 
961  QColor brushColor = mColor;
962  QColor penColor = mStrokeColor;
963 
964  brushColor.setAlphaF( mColor.alphaF() * context.opacity() );
965  penColor.setAlphaF( mStrokeColor.alphaF() * context.opacity() );
966 
967  mBrush = QBrush( brushColor );
968  mPen = QPen( penColor );
969  mPen.setStyle( mStrokeStyle );
970  mPen.setCapStyle( mPenCapStyle );
971  mPen.setJoinStyle( mPenJoinStyle );
973 
974  QColor selBrushColor = context.renderContext().selectionColor();
975  QColor selPenColor = selBrushColor == mColor ? selBrushColor : mStrokeColor;
976  if ( context.opacity() < 1 && !SELECTION_IS_OPAQUE )
977  {
978  selBrushColor.setAlphaF( context.opacity() );
979  selPenColor.setAlphaF( context.opacity() );
980  }
981  mSelBrush = QBrush( selBrushColor );
982  mSelPen = QPen( selPenColor );
983  mSelPen.setStyle( mStrokeStyle );
985 
987  const bool hasDataDefinedSize = mDataDefinedProperties.isActive( QgsSymbolLayer::PropertySize );
988 
989  // use caching only when:
990  // - size, rotation, shape, color, stroke color is not data-defined
991  // - drawing to screen (not printer)
992  mUsingCache = !hasDataDefinedRotation && !hasDataDefinedSize && !context.renderContext().forceVectorOutput()
996 
997  if ( mUsingCache )
998  mCachedOpacity = context.opacity();
999 
1000  if ( !shapeIsFilled( mShape ) )
1001  {
1002  // some markers can't be drawn as a polygon (circle, cross)
1003  // For these set the selected stroke color to the selected color
1004  mSelPen.setColor( selBrushColor );
1005  }
1006 
1007 
1008  if ( mUsingCache )
1009  {
1010  if ( !prepareCache( context ) )
1011  {
1012  mUsingCache = false;
1013  }
1014  }
1015  else
1016  {
1017  mCache = QImage();
1018  mSelCache = QImage();
1019  }
1020 }
1021 
1022 
1024 {
1025  double scaledSize = context.renderContext().convertToPainterUnits( mSize, mSizeUnit, mSizeMapUnitScale );
1027  {
1028  // rendering for symbol previews -- a size in meters in map units can't be calculated, so treat the size as millimeters
1029  // and clamp it to a reasonable range. It's the best we can do in this situation!
1030  scaledSize = std::min( std::max( context.renderContext().convertToPainterUnits( mSize, QgsUnitTypes::RenderMillimeters ), 3.0 ), 100.0 );
1031  }
1032 
1033  // take into account angle (which is not data-defined otherwise cache wouldn't be used)
1034  if ( !qgsDoubleNear( mAngle, 0.0 ) )
1035  {
1036  scaledSize = ( std::abs( std::sin( mAngle * M_PI / 180 ) ) + std::abs( std::cos( mAngle * M_PI / 180 ) ) ) * scaledSize;
1037  }
1038  // calculate necessary image size for the cache
1039  const double pw = static_cast< int >( std::round( ( ( qgsDoubleNear( mPen.widthF(), 0.0 ) ? 1 : mPen.widthF() * 4 ) + 1 ) ) ) / 2 * 2; // make even (round up); handle cosmetic pen
1040  const int imageSize = ( static_cast< int >( scaledSize ) + pw ) / 2 * 2 + 1; // make image width, height odd; account for pen width
1041  const double center = imageSize / 2.0;
1042  if ( imageSize > MAXIMUM_CACHE_WIDTH )
1043  {
1044  return false;
1045  }
1046 
1047  mCache = QImage( QSize( imageSize, imageSize ), QImage::Format_ARGB32_Premultiplied );
1048  mCache.fill( 0 );
1049 
1050  const bool needsBrush = shapeIsFilled( mShape );
1051 
1052  QPainter p;
1053  p.begin( &mCache );
1054  p.setRenderHint( QPainter::Antialiasing );
1055  p.setBrush( needsBrush ? mBrush : Qt::NoBrush );
1056  p.setPen( mPen );
1057  p.translate( QPointF( center, center ) );
1058  drawMarker( &p, context );
1059  p.end();
1060 
1061  // Construct the selected version of the Cache
1062 
1063  const QColor selColor = context.renderContext().selectionColor();
1064 
1065  mSelCache = QImage( QSize( imageSize, imageSize ), QImage::Format_ARGB32_Premultiplied );
1066  mSelCache.fill( 0 );
1067 
1068  p.begin( &mSelCache );
1069  p.setRenderHint( QPainter::Antialiasing );
1070  p.setBrush( needsBrush ? mSelBrush : Qt::NoBrush );
1071  p.setPen( mSelPen );
1072  p.translate( QPointF( center, center ) );
1073  drawMarker( &p, context );
1074  p.end();
1075 
1076  // Check that the selected version is different. If not, then re-render,
1077  // filling the background with the selection color and using the normal
1078  // colors for the symbol .. could be ugly!
1079 
1080  if ( mSelCache == mCache )
1081  {
1082  p.begin( &mSelCache );
1083  p.setRenderHint( QPainter::Antialiasing );
1084  p.fillRect( 0, 0, imageSize, imageSize, selColor );
1085  p.setBrush( needsBrush ? mBrush : Qt::NoBrush );
1086  p.setPen( mPen );
1087  p.translate( QPointF( center, center ) );
1088  drawMarker( &p, context );
1089  p.end();
1090  }
1091 
1092  return true;
1093 }
1094 
1095 void QgsSimpleMarkerSymbolLayer::draw( QgsSymbolRenderContext &context, Qgis::MarkerShape shape, const QPolygonF &polygon, const QPainterPath &path )
1096 {
1097  //making changes here? Don't forget to also update ::bounds if the changes affect the bounding box
1098  //of the rendered point!
1099 
1100  QPainter *p = context.renderContext().painter();
1101  if ( !p )
1102  {
1103  return;
1104  }
1105 
1106  QColor brushColor = mColor;
1107  brushColor.setAlphaF( brushColor.alphaF() * context.opacity() );
1108  mBrush.setColor( brushColor );
1109 
1110  QColor penColor = mStrokeColor;
1111  penColor.setAlphaF( penColor.alphaF() * context.opacity() );
1112  mPen.setColor( penColor );
1113 
1114  bool ok = true;
1116  {
1119  if ( ok )
1120  {
1121  c.setAlphaF( c.alphaF() * context.opacity() );
1122  mBrush.setColor( c );
1123  }
1124  }
1126  {
1129  if ( ok )
1130  {
1131  c.setAlphaF( c.alphaF() * context.opacity() );
1132  mPen.setColor( c );
1133  mSelPen.setColor( c );
1134  }
1135  }
1137  {
1140  if ( ok )
1141  {
1144  }
1145  }
1147  {
1150  if ( ok )
1151  {
1154  }
1155  }
1157  {
1159  const QString style = mDataDefinedProperties.valueAsString( QgsSymbolLayer::PropertyJoinStyle, context.renderContext().expressionContext(), QString(), &ok );
1160  if ( ok )
1161  {
1162  mPen.setJoinStyle( QgsSymbolLayerUtils::decodePenJoinStyle( style ) );
1163  mSelPen.setJoinStyle( QgsSymbolLayerUtils::decodePenJoinStyle( style ) );
1164  }
1165  }
1167  {
1169  const QString style = mDataDefinedProperties.valueAsString( QgsSymbolLayer::PropertyCapStyle, context.renderContext().expressionContext(), QString(), &ok );
1170  if ( ok )
1171  {
1172  mPen.setCapStyle( QgsSymbolLayerUtils::decodePenCapStyle( style ) );
1173  mSelPen.setCapStyle( QgsSymbolLayerUtils::decodePenCapStyle( style ) );
1174  }
1175  }
1176 
1177  if ( shapeIsFilled( shape ) )
1178  {
1179  p->setBrush( context.selected() ? mSelBrush : mBrush );
1180  }
1181  else
1182  {
1183  p->setBrush( Qt::NoBrush );
1184  }
1185  p->setPen( context.selected() ? mSelPen : mPen );
1186 
1187  if ( !polygon.isEmpty() )
1188  p->drawPolygon( polygon );
1189  else
1190  p->drawPath( path );
1191 }
1192 
1194 {
1195  //making changes here? Don't forget to also update ::bounds if the changes affect the bounding box
1196  //of the rendered point!
1197 
1198  QPainter *p = context.renderContext().painter();
1199  if ( !p )
1200  {
1201  return;
1202  }
1203 
1204  if ( mUsingCache && qgsDoubleNear( mCachedOpacity, context.opacity() ) )
1205  {
1206  const QImage &img = context.selected() ? mSelCache : mCache;
1207  const double s = img.width();
1208 
1209  bool hasDataDefinedSize = false;
1210  const double scaledSize = calculateSize( context, hasDataDefinedSize );
1211 
1212  bool hasDataDefinedRotation = false;
1213  QPointF offset;
1214  double angle = 0;
1215  calculateOffsetAndRotation( context, scaledSize, hasDataDefinedRotation, offset, angle );
1216 
1217  p->drawImage( QRectF( point.x() - s / 2.0 + offset.x(),
1218  point.y() - s / 2.0 + offset.y(),
1219  s, s ), img );
1220  }
1221  else
1222  {
1224  }
1225 }
1226 
1228 {
1229  QVariantMap map;
1230  map[QStringLiteral( "name" )] = encodeShape( mShape );
1231  map[QStringLiteral( "color" )] = QgsSymbolLayerUtils::encodeColor( mColor );
1232  map[QStringLiteral( "outline_color" )] = QgsSymbolLayerUtils::encodeColor( mStrokeColor );
1233  map[QStringLiteral( "size" )] = QString::number( mSize );
1234  map[QStringLiteral( "size_unit" )] = QgsUnitTypes::encodeUnit( mSizeUnit );
1235  map[QStringLiteral( "size_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mSizeMapUnitScale );
1236  map[QStringLiteral( "angle" )] = QString::number( mAngle );
1237  map[QStringLiteral( "offset" )] = QgsSymbolLayerUtils::encodePoint( mOffset );
1238  map[QStringLiteral( "offset_unit" )] = QgsUnitTypes::encodeUnit( mOffsetUnit );
1239  map[QStringLiteral( "offset_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mOffsetMapUnitScale );
1240  map[QStringLiteral( "scale_method" )] = QgsSymbolLayerUtils::encodeScaleMethod( mScaleMethod );
1241  map[QStringLiteral( "outline_style" )] = QgsSymbolLayerUtils::encodePenStyle( mStrokeStyle );
1242  map[QStringLiteral( "outline_width" )] = QString::number( mStrokeWidth );
1243  map[QStringLiteral( "outline_width_unit" )] = QgsUnitTypes::encodeUnit( mStrokeWidthUnit );
1244  map[QStringLiteral( "outline_width_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mStrokeWidthMapUnitScale );
1245  map[QStringLiteral( "joinstyle" )] = QgsSymbolLayerUtils::encodePenJoinStyle( mPenJoinStyle );
1246  map[QStringLiteral( "cap_style" )] = QgsSymbolLayerUtils::encodePenCapStyle( mPenCapStyle );
1247  map[QStringLiteral( "horizontal_anchor_point" )] = QString::number( mHorizontalAnchorPoint );
1248  map[QStringLiteral( "vertical_anchor_point" )] = QString::number( mVerticalAnchorPoint );
1249  return map;
1250 }
1251 
1253 {
1255  m->setOffset( mOffset );
1256  m->setSizeUnit( mSizeUnit );
1258  m->setOffsetUnit( mOffsetUnit );
1268  copyPaintEffect( m );
1269  return m;
1270 }
1271 
1272 void QgsSimpleMarkerSymbolLayer::writeSldMarker( QDomDocument &doc, QDomElement &element, const QVariantMap &props ) const
1273 {
1274  // <Graphic>
1275  QDomElement graphicElem = doc.createElement( QStringLiteral( "se:Graphic" ) );
1276  element.appendChild( graphicElem );
1277 
1279  const double size = QgsSymbolLayerUtils::rescaleUom( mSize, mSizeUnit, props );
1281 
1282  // <Rotation>
1283  QString angleFunc;
1284  bool ok;
1285  const double angle = props.value( QStringLiteral( "angle" ), QStringLiteral( "0" ) ).toDouble( &ok );
1286  if ( !ok )
1287  {
1288  angleFunc = QStringLiteral( "%1 + %2" ).arg( props.value( QStringLiteral( "angle" ), QStringLiteral( "0" ) ).toString() ).arg( mAngle );
1289  }
1290  else if ( !qgsDoubleNear( angle + mAngle, 0.0 ) )
1291  {
1292  angleFunc = QString::number( angle + mAngle );
1293  }
1294  QgsSymbolLayerUtils::createRotationElement( doc, graphicElem, angleFunc );
1295 
1296  // <Displacement>
1297  const QPointF offset = QgsSymbolLayerUtils::rescaleUom( mOffset, mOffsetUnit, props );
1299 }
1300 
1301 QString QgsSimpleMarkerSymbolLayer::ogrFeatureStyle( double mmScaleFactor, double mapUnitScaleFactor ) const
1302 {
1303  Q_UNUSED( mmScaleFactor )
1304  Q_UNUSED( mapUnitScaleFactor )
1305 #if 0
1306  QString ogrType = "3"; //default is circle
1307  if ( mName == "square" )
1308  {
1309  ogrType = "5";
1310  }
1311  else if ( mName == "triangle" )
1312  {
1313  ogrType = "7";
1314  }
1315  else if ( mName == "star" )
1316  {
1317  ogrType = "9";
1318  }
1319  else if ( mName == "circle" )
1320  {
1321  ogrType = "3";
1322  }
1323  else if ( mName == "cross" )
1324  {
1325  ogrType = "0";
1326  }
1327  else if ( mName == "x" || mName == "cross2" )
1328  {
1329  ogrType = "1";
1330  }
1331  else if ( mName == "line" )
1332  {
1333  ogrType = "10";
1334  }
1335 
1336  QString ogrString;
1337  ogrString.append( "SYMBOL(" );
1338  ogrString.append( "id:" );
1339  ogrString.append( '\"' );
1340  ogrString.append( "ogr-sym-" );
1341  ogrString.append( ogrType );
1342  ogrString.append( '\"' );
1343  ogrString.append( ",c:" );
1344  ogrString.append( mColor.name() );
1345  ogrString.append( ",o:" );
1346  ogrString.append( mStrokeColor.name() );
1347  ogrString.append( QString( ",s:%1mm" ).arg( mSize ) );
1348  ogrString.append( ')' );
1349  return ogrString;
1350 #endif //0
1351 
1352  QString ogrString;
1353  ogrString.append( "PEN(" );
1354  ogrString.append( "c:" );
1355  ogrString.append( mColor.name() );
1356  ogrString.append( ",w:" );
1357  ogrString.append( QString::number( mSize ) );
1358  ogrString.append( "mm" );
1359  ogrString.append( ")" );
1360  return ogrString;
1361 }
1362 
1364 {
1365  QgsDebugMsgLevel( QStringLiteral( "Entered." ), 4 );
1366 
1367  QDomElement graphicElem = element.firstChildElement( QStringLiteral( "Graphic" ) );
1368  if ( graphicElem.isNull() )
1369  return nullptr;
1370 
1371  QString name = QStringLiteral( "square" );
1372  QColor color, strokeColor;
1373  double strokeWidth, size;
1374  Qt::PenStyle strokeStyle;
1375 
1377  return nullptr;
1378 
1379  double angle = 0.0;
1380  QString angleFunc;
1381  if ( QgsSymbolLayerUtils::rotationFromSldElement( graphicElem, angleFunc ) )
1382  {
1383  bool ok;
1384  const double d = angleFunc.toDouble( &ok );
1385  if ( ok )
1386  angle = d;
1387  }
1388 
1389  QPointF offset;
1391 
1392  const Qgis::MarkerShape shape = decodeShape( name );
1393 
1394  double scaleFactor = 1.0;
1395  const QString uom = element.attribute( QStringLiteral( "uom" ) );
1396  QgsUnitTypes::RenderUnit sldUnitSize = QgsSymbolLayerUtils::decodeSldUom( uom, &scaleFactor );
1397  size = size * scaleFactor;
1398  offset.setX( offset.x() * scaleFactor );
1399  offset.setY( offset.y() * scaleFactor );
1400 
1402  m->setOutputUnit( sldUnitSize );
1403  m->setColor( color );
1405  m->setAngle( angle );
1406  m->setOffset( offset );
1409  return m;
1410 }
1411 
1413 {
1414  Q_UNUSED( context )
1415 
1416  if ( mPolygon.count() != 0 )
1417  {
1418  p->drawPolygon( mPolygon );
1419  }
1420  else
1421  {
1422  p->drawPath( mPath );
1423  }
1424 }
1425 
1426 bool QgsSimpleMarkerSymbolLayer::writeDxf( QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, QgsSymbolRenderContext &context, QPointF shift ) const
1427 {
1428  //data defined size?
1429  double size = mSize;
1430 
1431  const bool hasDataDefinedSize = mDataDefinedProperties.isActive( QgsSymbolLayer::PropertySize );
1432 
1433  //data defined size
1434  bool ok = true;
1435  if ( hasDataDefinedSize )
1436  {
1438 
1439  if ( ok )
1440  {
1441  switch ( mScaleMethod )
1442  {
1444  size = std::sqrt( size );
1445  break;
1447  break;
1448  }
1449  }
1450 
1452  }
1453 
1455  {
1456  size *= mmMapUnitScaleFactor;
1457  }
1458 
1460  {
1462  }
1463  const double halfSize = size / 2.0;
1464 
1465  //strokeWidth
1466  double strokeWidth = mStrokeWidth;
1467 
1469  {
1472  }
1475  {
1477  }
1478 
1479  //color
1480  QColor pc = mPen.color();
1481  QColor bc = mBrush.color();
1483  {
1486  }
1488  {
1491  }
1492 
1493  //offset
1494  double offsetX = 0;
1495  double offsetY = 0;
1496  markerOffset( context, offsetX, offsetY );
1497  offsetX *= context.renderContext().mapToPixel().mapUnitsPerPixel();
1498  offsetY *= context.renderContext().mapToPixel().mapUnitsPerPixel();
1499 
1500 
1501  QPointF off( offsetX, offsetY );
1502 
1503  //angle
1504  double angle = mAngle + mLineAngle;
1506  {
1507  context.setOriginalValueVariable( mAngle );
1509  }
1510 
1513  {
1515  const QString shapeName = mDataDefinedProperties.valueAsString( QgsSymbolLayer::PropertyName, context.renderContext().expressionContext(), QString(), &ok );
1516  if ( ok )
1517  {
1518  shape = decodeShape( shapeName, &ok );
1519  if ( !ok )
1520  shape = mShape;
1521  }
1522  }
1523 
1524  if ( angle )
1525  off = _rotatedOffset( off, angle );
1526 
1528 
1529  QTransform t;
1530  t.translate( shift.x() + off.x(), shift.y() - off.y() );
1531 
1532  if ( !qgsDoubleNear( angle, 0.0 ) )
1533  t.rotate( -angle );
1534 
1535  QPolygonF polygon;
1536  if ( shapeToPolygon( shape, polygon ) )
1537  {
1538  t.scale( halfSize, -halfSize );
1539 
1540  polygon = t.map( polygon );
1541 
1542  QgsPointSequence p;
1543  p.reserve( polygon.size() );
1544  for ( int i = 0; i < polygon.size(); i++ )
1545  {
1546  p << QgsPoint( polygon[i] );
1547  }
1548 
1549  if ( mBrush.style() != Qt::NoBrush )
1550  e.writePolygon( QgsRingSequence() << p, layerName, QStringLiteral( "SOLID" ), bc );
1551  if ( mPen.style() != Qt::NoPen )
1552  e.writePolyline( p, layerName, QStringLiteral( "CONTINUOUS" ), pc, strokeWidth );
1553  }
1554  else if ( shape == Qgis::MarkerShape::Circle )
1555  {
1556  shift += QPointF( off.x(), -off.y() );
1557  if ( mBrush.style() != Qt::NoBrush )
1558  e.writeFilledCircle( layerName, bc, QgsPoint( shift ), halfSize );
1559  if ( mPen.style() != Qt::NoPen )
1560  e.writeCircle( layerName, pc, QgsPoint( shift ), halfSize, QStringLiteral( "CONTINUOUS" ), strokeWidth );
1561  }
1562  else if ( shape == Qgis::MarkerShape::Line )
1563  {
1564  const QPointF pt1 = t.map( QPointF( 0, -halfSize ) );
1565  const QPointF pt2 = t.map( QPointF( 0, halfSize ) );
1566 
1567  if ( mPen.style() != Qt::NoPen )
1568  e.writeLine( QgsPoint( pt1 ), QgsPoint( pt2 ), layerName, QStringLiteral( "CONTINUOUS" ), pc, strokeWidth );
1569  }
1570  else if ( shape == Qgis::MarkerShape::Cross )
1571  {
1572  if ( mPen.style() != Qt::NoPen )
1573  {
1574  const QPointF pt1 = t.map( QPointF( -halfSize, 0 ) );
1575  const QPointF pt2 = t.map( QPointF( halfSize, 0 ) );
1576  const QPointF pt3 = t.map( QPointF( 0, -halfSize ) );
1577  const QPointF pt4 = t.map( QPointF( 0, halfSize ) );
1578 
1579  e.writeLine( QgsPoint( pt1 ), QgsPoint( pt2 ), layerName, QStringLiteral( "CONTINUOUS" ), pc, strokeWidth );
1580  e.writeLine( QgsPoint( pt3 ), QgsPoint( pt4 ), layerName, QStringLiteral( "CONTINUOUS" ), pc, strokeWidth );
1581  }
1582  }
1583  else if ( shape == Qgis::MarkerShape::Cross2 )
1584  {
1585  if ( mPen.style() != Qt::NoPen )
1586  {
1587  const QPointF pt1 = t.map( QPointF( -halfSize, -halfSize ) );
1588  const QPointF pt2 = t.map( QPointF( halfSize, halfSize ) );
1589  const QPointF pt3 = t.map( QPointF( halfSize, -halfSize ) );
1590  const QPointF pt4 = t.map( QPointF( -halfSize, halfSize ) );
1591 
1592  e.writeLine( QgsPoint( pt1 ), QgsPoint( pt2 ), layerName, QStringLiteral( "CONTINUOUS" ), pc, strokeWidth );
1593  e.writeLine( QgsPoint( pt3 ), QgsPoint( pt4 ), layerName, QStringLiteral( "CONTINUOUS" ), pc, strokeWidth );
1594  }
1595  }
1596  else if ( shape == Qgis::MarkerShape::ArrowHead )
1597  {
1598  if ( mPen.style() != Qt::NoPen )
1599  {
1600  const QPointF pt1 = t.map( QPointF( -halfSize, halfSize ) );
1601  const QPointF pt2 = t.map( QPointF( 0, 0 ) );
1602  const QPointF pt3 = t.map( QPointF( -halfSize, -halfSize ) );
1603 
1604  e.writeLine( QgsPoint( pt1 ), QgsPoint( pt2 ), layerName, QStringLiteral( "CONTINUOUS" ), pc, strokeWidth );
1605  e.writeLine( QgsPoint( pt3 ), QgsPoint( pt2 ), layerName, QStringLiteral( "CONTINUOUS" ), pc, strokeWidth );
1606  }
1607  }
1608  else
1609  {
1610  QgsDebugMsg( QStringLiteral( "Unsupported dxf marker name %1" ).arg( encodeShape( shape ) ) );
1611  return false;
1612  }
1613 
1614  return true;
1615 }
1616 
1617 
1619 {
1621  mStrokeWidthUnit = unit;
1622 }
1623 
1625 {
1627  {
1628  return mStrokeWidthUnit;
1629  }
1631 }
1632 
1634 {
1636  mStrokeWidthMapUnitScale = scale;
1637 }
1638 
1640 {
1642  {
1643  return mStrokeWidthMapUnitScale;
1644  }
1645  return QgsMapUnitScale();
1646 }
1647 
1649 {
1653 }
1654 
1656 {
1657  QRectF symbolBounds = QgsSimpleMarkerSymbolLayerBase::bounds( point, context );
1658 
1659  // need to account for stroke width
1660  double penWidth = mStrokeWidth;
1661  bool ok = true;
1663  {
1666  if ( ok )
1667  {
1668  penWidth = strokeWidth;
1669  }
1670  }
1673  {
1676  if ( ok && strokeStyle == QLatin1String( "no" ) )
1677  {
1678  penWidth = 0.0;
1679  }
1680  }
1681  else if ( mStrokeStyle == Qt::NoPen )
1682  penWidth = 0;
1683 
1684  //antialiasing, add 1 pixel
1685  penWidth += 1;
1686 
1687  //extend bounds by pen width / 2.0
1688  symbolBounds.adjust( -penWidth / 2.0, -penWidth / 2.0,
1689  penWidth / 2.0, penWidth / 2.0 );
1690 
1691  return symbolBounds;
1692 }
1693 
1694 void QgsSimpleMarkerSymbolLayer::setColor( const QColor &color )
1695 {
1696  if ( shapeIsFilled( mShape ) )
1697  {
1698  setFillColor( color );
1699  }
1700  else
1701  {
1702  setStrokeColor( color );
1703  }
1704 }
1705 
1707 {
1708  if ( shapeIsFilled( mShape ) )
1709  {
1710  return fillColor();
1711  }
1712  else
1713  {
1714  return strokeColor();
1715  }
1716 }
1717 
1718 
1719 
1720 
1721 //
1722 // QgsFilledMarkerSymbolLayer
1723 //
1724 
1726  : QgsSimpleMarkerSymbolLayerBase( shape, size, angle, scaleMethod )
1727 {
1728  mFill.reset( static_cast<QgsFillSymbol *>( QgsFillSymbol::createSimple( QVariantMap() ) ) );
1729 }
1730 
1732 
1734 {
1735  QString name = DEFAULT_SIMPLEMARKER_NAME;
1739 
1740  if ( props.contains( QStringLiteral( "name" ) ) )
1741  name = props[QStringLiteral( "name" )].toString();
1742  if ( props.contains( QStringLiteral( "size" ) ) )
1743  size = props[QStringLiteral( "size" )].toDouble();
1744  if ( props.contains( QStringLiteral( "angle" ) ) )
1745  angle = props[QStringLiteral( "angle" )].toDouble();
1746  if ( props.contains( QStringLiteral( "scale_method" ) ) )
1747  scaleMethod = QgsSymbolLayerUtils::decodeScaleMethod( props[QStringLiteral( "scale_method" )].toString() );
1748 
1750  if ( props.contains( QStringLiteral( "offset" ) ) )
1751  m->setOffset( QgsSymbolLayerUtils::decodePoint( props[QStringLiteral( "offset" )].toString() ) );
1752  if ( props.contains( QStringLiteral( "offset_unit" ) ) )
1753  m->setOffsetUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "offset_unit" )].toString() ) );
1754  if ( props.contains( QStringLiteral( "offset_map_unit_scale" ) ) )
1755  m->setOffsetMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "offset_map_unit_scale" )].toString() ) );
1756  if ( props.contains( QStringLiteral( "size_unit" ) ) )
1757  m->setSizeUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "size_unit" )].toString() ) );
1758  if ( props.contains( QStringLiteral( "size_map_unit_scale" ) ) )
1759  m->setSizeMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "size_map_unit_scale" )].toString() ) );
1760  if ( props.contains( QStringLiteral( "horizontal_anchor_point" ) ) )
1761  {
1762  m->setHorizontalAnchorPoint( QgsMarkerSymbolLayer::HorizontalAnchorPoint( props[ QStringLiteral( "horizontal_anchor_point" )].toInt() ) );
1763  }
1764  if ( props.contains( QStringLiteral( "vertical_anchor_point" ) ) )
1765  {
1766  m->setVerticalAnchorPoint( QgsMarkerSymbolLayer::VerticalAnchorPoint( props[ QStringLiteral( "vertical_anchor_point" )].toInt() ) );
1767  }
1768 
1770 
1771  m->restoreOldDataDefinedProperties( props );
1772 
1773  return m;
1774 }
1775 
1777 {
1778  return QStringLiteral( "FilledMarker" );
1779 }
1780 
1782 {
1783  if ( mFill )
1784  {
1785  mFill->startRender( context.renderContext(), context.fields() );
1786  }
1787 
1789 }
1790 
1792 {
1793  if ( mFill )
1794  {
1795  mFill->stopRender( context.renderContext() );
1796  }
1797 }
1798 
1800 {
1801  QVariantMap map;
1802  map[QStringLiteral( "name" )] = encodeShape( mShape );
1803  map[QStringLiteral( "size" )] = QString::number( mSize );
1804  map[QStringLiteral( "size_unit" )] = QgsUnitTypes::encodeUnit( mSizeUnit );
1805  map[QStringLiteral( "size_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mSizeMapUnitScale );
1806  map[QStringLiteral( "angle" )] = QString::number( mAngle );
1807  map[QStringLiteral( "offset" )] = QgsSymbolLayerUtils::encodePoint( mOffset );
1808  map[QStringLiteral( "offset_unit" )] = QgsUnitTypes::encodeUnit( mOffsetUnit );
1809  map[QStringLiteral( "offset_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mOffsetMapUnitScale );
1810  map[QStringLiteral( "scale_method" )] = QgsSymbolLayerUtils::encodeScaleMethod( mScaleMethod );
1811  map[QStringLiteral( "horizontal_anchor_point" )] = QString::number( mHorizontalAnchorPoint );
1812  map[QStringLiteral( "vertical_anchor_point" )] = QString::number( mVerticalAnchorPoint );
1813 
1814  if ( mFill )
1815  {
1816  map[QStringLiteral( "color" )] = QgsSymbolLayerUtils::encodeColor( mFill->color() );
1817  }
1818  return map;
1819 }
1820 
1822 {
1824  copyPaintEffect( m );
1826  m->setSubSymbol( mFill->clone() );
1827  return m;
1828 }
1829 
1831 {
1832  return mFill.get();
1833 }
1834 
1836 {
1837  if ( symbol && symbol->type() == Qgis::SymbolType::Fill )
1838  {
1839  mFill.reset( static_cast<QgsFillSymbol *>( symbol ) );
1840  return true;
1841  }
1842  else
1843  {
1844  delete symbol;
1845  return false;
1846  }
1847 }
1848 
1850 {
1851  if ( mFill )
1852  {
1853  return QgsSymbolLayerUtils::estimateMaxSymbolBleed( mFill.get(), context );
1854  }
1855  return 0;
1856 }
1857 
1859 {
1860  QSet<QString> attr = QgsSimpleMarkerSymbolLayerBase::usedAttributes( context );
1861  if ( mFill )
1862  attr.unite( mFill->usedAttributes( context ) );
1863  return attr;
1864 }
1865 
1867 {
1869  return true;
1870  if ( mFill && mFill->hasDataDefinedProperties() )
1871  return true;
1872  return false;
1873 }
1874 
1876 {
1877  mColor = c;
1878  if ( mFill )
1879  mFill->setColor( c );
1880 }
1881 
1883 {
1884  return mFill ? mFill->color() : mColor;
1885 }
1886 
1888 {
1891  || ( mFill && mFill->usesMapUnits() );
1892 }
1893 
1895 {
1897  if ( mFill )
1898  mFill->setOutputUnit( unit );
1899 }
1900 
1901 void QgsFilledMarkerSymbolLayer::draw( QgsSymbolRenderContext &context, Qgis::MarkerShape shape, const QPolygonF &polygon, const QPainterPath &path )
1902 {
1903  //making changes here? Don't forget to also update ::bounds if the changes affect the bounding box
1904  //of the rendered point!
1905 
1906  QPainter *p = context.renderContext().painter();
1907  if ( !p )
1908  {
1909  return;
1910  }
1911 
1912  const double prevOpacity = mFill->opacity();
1913  mFill->setOpacity( mFill->opacity() * context.opacity() );
1914 
1915  if ( shapeIsFilled( shape ) )
1916  {
1917  p->setBrush( Qt::red );
1918  }
1919  else
1920  {
1921  p->setBrush( Qt::NoBrush );
1922  }
1923  p->setPen( Qt::black );
1924 
1925  const bool prevIsSubsymbol = context.renderContext().flags() & Qgis::RenderContextFlag::RenderingSubSymbol;
1927 
1928  if ( !polygon.isEmpty() )
1929  {
1930  mFill->renderPolygon( polygon, /* rings */ nullptr, context.feature(), context.renderContext(), -1, context.selected() );
1931  }
1932  else
1933  {
1934  const QPolygonF poly = path.toFillPolygon();
1935  mFill->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext(), -1, context.selected() );
1936  }
1937 
1939 
1940  mFill->setOpacity( prevOpacity );
1941 }
1942 
1943 
1945 
1946 
1947 QgsSvgMarkerSymbolLayer::QgsSvgMarkerSymbolLayer( const QString &path, double size, double angle, Qgis::ScaleMethod scaleMethod )
1948 {
1949  mSize = size;
1950  mAngle = angle;
1951  mOffset = QPointF( 0, 0 );
1953  mStrokeWidth = 0.2;
1955  mColor = QColor( 35, 35, 35 );
1956  mStrokeColor = QColor( 35, 35, 35 );
1957  setPath( path );
1958 }
1959 
1961 
1963 {
1964  QString name;
1965  double size = DEFAULT_SVGMARKER_SIZE;
1966  double angle = DEFAULT_SVGMARKER_ANGLE;
1968 
1969  if ( props.contains( QStringLiteral( "name" ) ) )
1970  name = props[QStringLiteral( "name" )].toString();
1971  if ( props.contains( QStringLiteral( "size" ) ) )
1972  size = props[QStringLiteral( "size" )].toDouble();
1973  if ( props.contains( QStringLiteral( "angle" ) ) )
1974  angle = props[QStringLiteral( "angle" )].toDouble();
1975  if ( props.contains( QStringLiteral( "scale_method" ) ) )
1976  scaleMethod = QgsSymbolLayerUtils::decodeScaleMethod( props[QStringLiteral( "scale_method" )].toString() );
1977 
1979 
1980  if ( props.contains( QStringLiteral( "size_unit" ) ) )
1981  m->setSizeUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "size_unit" )].toString() ) );
1982  if ( props.contains( QStringLiteral( "size_map_unit_scale" ) ) )
1983  m->setSizeMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "size_map_unit_scale" )].toString() ) );
1984  if ( props.contains( QStringLiteral( "fixedAspectRatio" ) ) )
1985  m->setFixedAspectRatio( props[QStringLiteral( "fixedAspectRatio" )].toDouble() );
1986  if ( props.contains( QStringLiteral( "offset" ) ) )
1987  m->setOffset( QgsSymbolLayerUtils::decodePoint( props[QStringLiteral( "offset" )].toString() ) );
1988  if ( props.contains( QStringLiteral( "offset_unit" ) ) )
1989  m->setOffsetUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "offset_unit" )].toString() ) );
1990  if ( props.contains( QStringLiteral( "offset_map_unit_scale" ) ) )
1991  m->setOffsetMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "offset_map_unit_scale" )].toString() ) );
1992  if ( props.contains( QStringLiteral( "fill" ) ) )
1993  {
1994  //pre 2.5 projects used "fill"
1995  m->setFillColor( QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "fill" )].toString() ) );
1996  }
1997  else if ( props.contains( QStringLiteral( "color" ) ) )
1998  {
1999  m->setFillColor( QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "color" )].toString() ) );
2000  }
2001  if ( props.contains( QStringLiteral( "outline" ) ) )
2002  {
2003  //pre 2.5 projects used "outline"
2004  m->setStrokeColor( QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "outline" )].toString() ) );
2005  }
2006  else if ( props.contains( QStringLiteral( "outline_color" ) ) )
2007  {
2008  m->setStrokeColor( QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "outline_color" )].toString() ) );
2009  }
2010  else if ( props.contains( QStringLiteral( "line_color" ) ) )
2011  {
2012  m->setStrokeColor( QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "line_color" )].toString() ) );
2013  }
2014 
2015  if ( props.contains( QStringLiteral( "outline-width" ) ) )
2016  {
2017  //pre 2.5 projects used "outline-width"
2018  m->setStrokeWidth( props[QStringLiteral( "outline-width" )].toDouble() );
2019  }
2020  else if ( props.contains( QStringLiteral( "outline_width" ) ) )
2021  {
2022  m->setStrokeWidth( props[QStringLiteral( "outline_width" )].toDouble() );
2023  }
2024  else if ( props.contains( QStringLiteral( "line_width" ) ) )
2025  {
2026  m->setStrokeWidth( props[QStringLiteral( "line_width" )].toDouble() );
2027  }
2028 
2029  if ( props.contains( QStringLiteral( "outline_width_unit" ) ) )
2030  {
2031  m->setStrokeWidthUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "outline_width_unit" )].toString() ) );
2032  }
2033  else if ( props.contains( QStringLiteral( "line_width_unit" ) ) )
2034  {
2035  m->setStrokeWidthUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "line_width_unit" )].toString() ) );
2036  }
2037  if ( props.contains( QStringLiteral( "outline_width_map_unit_scale" ) ) )
2038  m->setStrokeWidthMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "outline_width_map_unit_scale" )].toString() ) );
2039 
2040  if ( props.contains( QStringLiteral( "horizontal_anchor_point" ) ) )
2041  {
2042  m->setHorizontalAnchorPoint( QgsMarkerSymbolLayer::HorizontalAnchorPoint( props[ QStringLiteral( "horizontal_anchor_point" )].toInt() ) );
2043  }
2044  if ( props.contains( QStringLiteral( "vertical_anchor_point" ) ) )
2045  {
2046  m->setVerticalAnchorPoint( QgsMarkerSymbolLayer::VerticalAnchorPoint( props[ QStringLiteral( "vertical_anchor_point" )].toInt() ) );
2047  }
2048 
2049  m->restoreOldDataDefinedProperties( props );
2050 
2052 
2053  if ( props.contains( QStringLiteral( "parameters" ) ) )
2054  {
2055  const QVariantMap parameters = props[QStringLiteral( "parameters" )].toMap();
2057  }
2058 
2059  return m;
2060 }
2061 
2062 void QgsSvgMarkerSymbolLayer::resolvePaths( QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving )
2063 {
2064  const QVariantMap::iterator it = properties.find( QStringLiteral( "name" ) );
2065  if ( it != properties.end() )
2066  {
2067  if ( saving )
2068  {
2069  it.value() = QgsSymbolLayerUtils::svgSymbolPathToName( it.value().toString(), pathResolver );
2070  }
2071  else
2072  {
2073  it.value() = QgsSymbolLayerUtils::svgSymbolNameToPath( it.value().toString(), pathResolver );
2074  }
2075  }
2076 }
2077 
2078 void QgsSvgMarkerSymbolLayer::setPath( const QString &path )
2079 {
2080  mDefaultAspectRatio = 0;
2081  mHasFillParam = false;
2082  mPath = path;
2083  QColor defaultFillColor, defaultStrokeColor;
2084  double strokeWidth, fillOpacity, strokeOpacity;
2085  bool hasFillOpacityParam = false, hasStrokeParam = false, hasStrokeWidthParam = false, hasStrokeOpacityParam = false;
2086  bool hasDefaultFillColor = false, hasDefaultFillOpacity = false, hasDefaultStrokeColor = false, hasDefaultStrokeWidth = false, hasDefaultStrokeOpacity = false;
2087  QgsApplication::svgCache()->containsParams( path, mHasFillParam, hasDefaultFillColor, defaultFillColor,
2088  hasFillOpacityParam, hasDefaultFillOpacity, fillOpacity,
2089  hasStrokeParam, hasDefaultStrokeColor, defaultStrokeColor,
2090  hasStrokeWidthParam, hasDefaultStrokeWidth, strokeWidth,
2091  hasStrokeOpacityParam, hasDefaultStrokeOpacity, strokeOpacity );
2092 
2093  const double newFillOpacity = hasFillOpacityParam ? fillColor().alphaF() : 1.0;
2094  const double newStrokeOpacity = hasStrokeOpacityParam ? strokeColor().alphaF() : 1.0;
2095 
2096  if ( hasDefaultFillColor )
2097  {
2098  defaultFillColor.setAlphaF( newFillOpacity );
2099  setFillColor( defaultFillColor );
2100  }
2101  if ( hasDefaultFillOpacity )
2102  {
2103  QColor c = fillColor();
2104  c.setAlphaF( fillOpacity );
2105  setFillColor( c );
2106  }
2107  if ( hasDefaultStrokeColor )
2108  {
2109  defaultStrokeColor.setAlphaF( newStrokeOpacity );
2110  setStrokeColor( defaultStrokeColor );
2111  }
2112  if ( hasDefaultStrokeWidth )
2113  {
2115  }
2116  if ( hasDefaultStrokeOpacity )
2117  {
2118  QColor c = strokeColor();
2119  c.setAlphaF( strokeOpacity );
2120  setStrokeColor( c );
2121  }
2122 
2124 }
2125 
2127 {
2128  if ( mDefaultAspectRatio == 0.0 )
2129  {
2130  //size
2131  const double size = mSize;
2132  //assume 88 dpi as standard value
2133  const double widthScaleFactor = 3.465;
2134  const QSizeF svgViewbox = QgsApplication::svgCache()->svgViewboxSize( mPath, size, mColor, mStrokeColor, mStrokeWidth, widthScaleFactor );
2135  // set default aspect ratio
2136  mDefaultAspectRatio = svgViewbox.isValid() ? svgViewbox.height() / svgViewbox.width() : 0.0;
2137  }
2138  return mDefaultAspectRatio;
2139 }
2140 
2142 {
2143  const bool aPreservedAspectRatio = preservedAspectRatio();
2144  if ( aPreservedAspectRatio && !par )
2145  {
2147  }
2148  else if ( !aPreservedAspectRatio && par )
2149  {
2150  mFixedAspectRatio = 0.0;
2151  }
2152  return preservedAspectRatio();
2153 }
2154 
2155 void QgsSvgMarkerSymbolLayer::setParameters( const QMap<QString, QgsProperty> &parameters )
2156 {
2158 }
2159 
2160 
2162 {
2163  return QStringLiteral( "SvgMarker" );
2164 }
2165 
2167 {
2168  QgsMarkerSymbolLayer::startRender( context ); // get anchor point expressions
2169  Q_UNUSED( context )
2170 }
2171 
2173 {
2174  Q_UNUSED( context )
2175 }
2176 
2178 {
2179  QPainter *p = context.renderContext().painter();
2180  if ( !p )
2181  return;
2182 
2183  bool hasDataDefinedSize = false;
2184  const double scaledWidth = calculateSize( context, hasDataDefinedSize );
2185  const double width = context.renderContext().convertToPainterUnits( scaledWidth, mSizeUnit, mSizeMapUnitScale );
2186 
2187  //don't render symbols with a width below one or above 10,000 pixels
2188  if ( static_cast< int >( width ) < 1 || 10000.0 < width )
2189  {
2190  return;
2191  }
2192 
2193  const QgsScopedQPainterState painterState( p );
2194 
2195  bool hasDataDefinedAspectRatio = false;
2196  const double aspectRatio = calculateAspectRatio( context, scaledWidth, hasDataDefinedAspectRatio );
2197  double scaledHeight = scaledWidth * ( !qgsDoubleNear( aspectRatio, 0.0 ) ? aspectRatio : mDefaultAspectRatio );
2198 
2200 
2201  double strokeWidth = mStrokeWidth;
2203  {
2206  }
2208 
2209  QColor fillColor = mColor;
2210  if ( context.selected() && mHasFillParam )
2211  {
2212  fillColor = context.renderContext().selectionColor();
2213  }
2215  {
2218  }
2219 
2220  QColor strokeColor = mStrokeColor;
2222  {
2225  }
2226 
2227  QString path = mPath;
2229  {
2230  context.setOriginalValueVariable( mPath );
2232  context.renderContext().pathResolver() );
2234  {
2235  // adjust height of data defined path
2236  const QSizeF svgViewbox = QgsApplication::svgCache()->svgViewboxSize( path, scaledWidth, fillColor, strokeColor, strokeWidth,
2237  context.renderContext().scaleFactor(), aspectRatio,
2238  ( context.renderContext().flags() & Qgis::RenderContextFlag::RenderBlocking ), evaluatedParameters );
2239  scaledHeight = svgViewbox.isValid() ? scaledWidth * svgViewbox.height() / svgViewbox.width() : scaledWidth;
2240  }
2241  }
2242 
2243  QPointF outputOffset;
2244  double angle = 0.0;
2245  calculateOffsetAndRotation( context, scaledWidth, scaledHeight, outputOffset, angle );
2246 
2247  p->translate( point + outputOffset );
2248 
2249  const bool rotated = !qgsDoubleNear( angle, 0 );
2250  if ( rotated )
2251  p->rotate( angle );
2252 
2253  bool fitsInCache = true;
2254  bool usePict = true;
2255  const bool rasterizeSelected = !mHasFillParam || mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyName );
2256  if ( ( !context.renderContext().forceVectorOutput() && !rotated ) || ( context.selected() && rasterizeSelected ) )
2257  {
2259  context.renderContext().scaleFactor(), fitsInCache, aspectRatio,
2260  ( context.renderContext().flags() & Qgis::RenderContextFlag::RenderBlocking ), evaluatedParameters );
2261  if ( fitsInCache && img.width() > 1 )
2262  {
2263  usePict = false;
2264 
2265  if ( context.selected() )
2266  {
2268  }
2269 
2270  //consider transparency
2271  if ( !qgsDoubleNear( context.opacity(), 1.0 ) )
2272  {
2273  QImage transparentImage = img.copy();
2274  QgsSymbolLayerUtils::multiplyImageOpacity( &transparentImage, context.opacity() );
2275  p->drawImage( -transparentImage.width() / 2.0, -transparentImage.height() / 2.0, transparentImage );
2276  }
2277  else
2278  {
2279  p->drawImage( -img.width() / 2.0, -img.height() / 2.0, img );
2280  }
2281  }
2282  }
2283 
2284  if ( usePict || !fitsInCache )
2285  {
2286  p->setOpacity( context.opacity() );
2287  const QPicture pct = QgsApplication::svgCache()->svgAsPicture( path, width, fillColor, strokeColor, strokeWidth,
2288  context.renderContext().scaleFactor(), context.renderContext().forceVectorOutput(), aspectRatio,
2289  ( context.renderContext().flags() & Qgis::RenderContextFlag::RenderBlocking ), evaluatedParameters );
2290  if ( pct.width() > 1 )
2291  {
2292  const QgsScopedQPainterState painterPictureState( p );
2293  _fixQPictureDPI( p );
2294  p->drawPicture( 0, 0, pct );
2295  }
2296  }
2297 
2298  // workaround issue with nested QPictures forgetting antialiasing flag - see https://github.com/qgis/QGIS/issues/22909
2300 }
2301 
2302 double QgsSvgMarkerSymbolLayer::calculateSize( QgsSymbolRenderContext &context, bool &hasDataDefinedSize ) const
2303 {
2304  double scaledSize = mSize;
2306 
2307  bool ok = true;
2308  if ( hasDataDefinedSize )
2309  {
2310  context.setOriginalValueVariable( mSize );
2312  }
2313  else
2314  {
2316  if ( hasDataDefinedSize )
2317  {
2318  context.setOriginalValueVariable( mSize );
2320  }
2321  }
2322 
2323  if ( hasDataDefinedSize && ok )
2324  {
2325  switch ( mScaleMethod )
2326  {
2328  scaledSize = std::sqrt( scaledSize );
2329  break;
2331  break;
2332  }
2333  }
2334 
2335  return scaledSize;
2336 }
2337 
2338 double QgsSvgMarkerSymbolLayer::calculateAspectRatio( QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedAspectRatio ) const
2339 {
2341  if ( !hasDataDefinedAspectRatio )
2342  return mFixedAspectRatio;
2343 
2345  return 0.0;
2346 
2347  double scaledAspectRatio = mDefaultAspectRatio;
2348  if ( mFixedAspectRatio > 0.0 )
2349  scaledAspectRatio = mFixedAspectRatio;
2350 
2351  const double defaultHeight = mSize * scaledAspectRatio;
2352  scaledAspectRatio = defaultHeight / scaledSize;
2353 
2354  bool ok = true;
2355  double scaledHeight = scaledSize * scaledAspectRatio;
2357  {
2358  context.setOriginalValueVariable( defaultHeight );
2359  scaledHeight = mDataDefinedProperties.valueAsDouble( QgsSymbolLayer::PropertyHeight, context.renderContext().expressionContext(), defaultHeight, &ok );
2360  }
2361 
2362  if ( hasDataDefinedAspectRatio && ok )
2363  {
2364  switch ( mScaleMethod )
2365  {
2367  scaledHeight = sqrt( scaledHeight );
2368  break;
2370  break;
2371  }
2372  }
2373 
2374  scaledAspectRatio = scaledHeight / scaledSize;
2375 
2376  return scaledAspectRatio;
2377 }
2378 
2379 void QgsSvgMarkerSymbolLayer::calculateOffsetAndRotation( QgsSymbolRenderContext &context, double scaledWidth, double scaledHeight, QPointF &offset, double &angle ) const
2380 {
2381  //offset
2382  double offsetX = 0;
2383  double offsetY = 0;
2384  markerOffset( context, scaledWidth, scaledHeight, offsetX, offsetY );
2385  offset = QPointF( offsetX, offsetY );
2386 
2387  angle = mAngle + mLineAngle;
2389  {
2390  context.setOriginalValueVariable( mAngle );
2392  }
2393 
2395  if ( hasDataDefinedRotation )
2396  {
2397  // For non-point markers, "dataDefinedRotation" means following the
2398  // shape (shape-data defined). For them, "field-data defined" does
2399  // not work at all. TODO: if "field-data defined" ever gets implemented
2400  // we'll need a way to distinguish here between the two, possibly
2401  // using another flag in renderHints()
2402  const QgsFeature *f = context.feature();
2403  if ( f )
2404  {
2405  if ( f->hasGeometry() && f->geometry().type() == QgsWkbTypes::PointGeometry )
2406  {
2407  const QgsMapToPixel &m2p = context.renderContext().mapToPixel();
2408  angle += m2p.mapRotation();
2409  }
2410  }
2411  }
2412 
2413  if ( angle )
2415 }
2416 
2417 
2419 {
2420  QVariantMap map;
2421  map[QStringLiteral( "name" )] = mPath;
2422  map[QStringLiteral( "size" )] = QString::number( mSize );
2423  map[QStringLiteral( "size_unit" )] = QgsUnitTypes::encodeUnit( mSizeUnit );
2424  map[QStringLiteral( "size_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mSizeMapUnitScale );
2425  map[QStringLiteral( "fixedAspectRatio" )] = QString::number( mFixedAspectRatio );
2426  map[QStringLiteral( "angle" )] = QString::number( mAngle );
2427  map[QStringLiteral( "offset" )] = QgsSymbolLayerUtils::encodePoint( mOffset );
2428  map[QStringLiteral( "offset_unit" )] = QgsUnitTypes::encodeUnit( mOffsetUnit );
2429  map[QStringLiteral( "offset_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mOffsetMapUnitScale );
2430  map[QStringLiteral( "scale_method" )] = QgsSymbolLayerUtils::encodeScaleMethod( mScaleMethod );
2431  map[QStringLiteral( "color" )] = QgsSymbolLayerUtils::encodeColor( mColor );
2432  map[QStringLiteral( "outline_color" )] = QgsSymbolLayerUtils::encodeColor( mStrokeColor );
2433  map[QStringLiteral( "outline_width" )] = QString::number( mStrokeWidth );
2434  map[QStringLiteral( "outline_width_unit" )] = QgsUnitTypes::encodeUnit( mStrokeWidthUnit );
2435  map[QStringLiteral( "outline_width_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mStrokeWidthMapUnitScale );
2436  map[QStringLiteral( "horizontal_anchor_point" )] = QString::number( mHorizontalAnchorPoint );
2437  map[QStringLiteral( "vertical_anchor_point" )] = QString::number( mVerticalAnchorPoint );
2438 
2439  map[QStringLiteral( "parameters" )] = QgsProperty::propertyMapToVariantMap( mParameters );
2440 
2441  return map;
2442 }
2443 
2445 {
2449 }
2450 
2452 {
2455  m->setColor( mColor );
2460  m->setOffset( mOffset );
2461  m->setOffsetUnit( mOffsetUnit );
2463  m->setSizeUnit( mSizeUnit );
2467  m->setParameters( mParameters );
2468 
2470  copyPaintEffect( m );
2471  return m;
2472 }
2473 
2475 {
2477  mStrokeWidthUnit = unit;
2478 }
2479 
2481 {
2483  if ( unit != mStrokeWidthUnit )
2484  {
2486  }
2487  return unit;
2488 }
2489 
2491 {
2493  mStrokeWidthMapUnitScale = scale;
2494 }
2495 
2497 {
2499  {
2500  return mStrokeWidthMapUnitScale;
2501  }
2502  return QgsMapUnitScale();
2503 }
2504 
2505 void QgsSvgMarkerSymbolLayer::writeSldMarker( QDomDocument &doc, QDomElement &element, const QVariantMap &props ) const
2506 {
2507  // <Graphic>
2508  QDomElement graphicElem = doc.createElement( QStringLiteral( "se:Graphic" ) );
2509  element.appendChild( graphicElem );
2510 
2511  // encode a parametric SVG reference
2512  const double size = QgsSymbolLayerUtils::rescaleUom( mSize, mSizeUnit, props );
2515 
2516  // <Rotation>
2517  QString angleFunc;
2518  bool ok;
2519  const double angle = props.value( QStringLiteral( "angle" ), QStringLiteral( "0" ) ).toDouble( &ok );
2520  if ( !ok )
2521  {
2522  angleFunc = QStringLiteral( "%1 + %2" ).arg( props.value( QStringLiteral( "angle" ), QStringLiteral( "0" ) ).toString() ).arg( mAngle );
2523  }
2524  else if ( !qgsDoubleNear( angle + mAngle, 0.0 ) )
2525  {
2526  angleFunc = QString::number( angle + mAngle );
2527  }
2528 
2529  QgsSymbolLayerUtils::createRotationElement( doc, graphicElem, angleFunc );
2530 
2531  // <Displacement>
2532  const QPointF offset = QgsSymbolLayerUtils::rescaleUom( mOffset, mOffsetUnit, props );
2534 }
2535 
2537 {
2538  QgsDebugMsgLevel( QStringLiteral( "Entered." ), 4 );
2539 
2540  QDomElement graphicElem = element.firstChildElement( QStringLiteral( "Graphic" ) );
2541  if ( graphicElem.isNull() )
2542  return nullptr;
2543 
2544  QString path, mimeType;
2545  QColor fillColor;
2546  double size;
2547 
2548  if ( !QgsSymbolLayerUtils::externalGraphicFromSld( graphicElem, path, mimeType, fillColor, size ) )
2549  return nullptr;
2550 
2551  double scaleFactor = 1.0;
2552  const QString uom = element.attribute( QStringLiteral( "uom" ) );
2553  QgsUnitTypes::RenderUnit sldUnitSize = QgsSymbolLayerUtils::decodeSldUom( uom, &scaleFactor );
2554  size = size * scaleFactor;
2555 
2556  if ( mimeType != QLatin1String( "image/svg+xml" ) )
2557  return nullptr;
2558 
2559  double angle = 0.0;
2560  QString angleFunc;
2561  if ( QgsSymbolLayerUtils::rotationFromSldElement( graphicElem, angleFunc ) )
2562  {
2563  bool ok;
2564  const double d = angleFunc.toDouble( &ok );
2565  if ( ok )
2566  angle = d;
2567  }
2568 
2569  QPointF offset;
2571 
2573  m->setOutputUnit( sldUnitSize );
2574  m->setFillColor( fillColor );
2575  //m->setStrokeColor( strokeColor );
2576  //m->setStrokeWidth( strokeWidth );
2577  m->setAngle( angle );
2578  m->setOffset( offset );
2579  return m;
2580 }
2581 
2582 bool QgsSvgMarkerSymbolLayer::writeDxf( QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, QgsSymbolRenderContext &context, QPointF shift ) const
2583 {
2584  //size
2585  double size = mSize;
2586 
2587  const bool hasDataDefinedSize = mDataDefinedProperties.isActive( QgsSymbolLayer::PropertySize );
2588 
2589  bool ok = true;
2590  if ( hasDataDefinedSize )
2591  {
2592  context.setOriginalValueVariable( mSize );
2594  }
2595 
2596  if ( hasDataDefinedSize && ok )
2597  {
2598  switch ( mScaleMethod )
2599  {
2601  size = std::sqrt( size );
2602  break;
2604  break;
2605  }
2606  }
2607 
2609  {
2610  size *= mmMapUnitScaleFactor;
2611  }
2612 
2613  //offset, angle
2614  QPointF offset = mOffset;
2615 
2617  {
2619  const QVariant val = mDataDefinedProperties.value( QgsSymbolLayer::PropertyOffset, context.renderContext().expressionContext(), QString() );
2620  const QPointF res = QgsSymbolLayerUtils::toPoint( val, &ok );
2621  if ( ok )
2622  offset = res;
2623  }
2624  const double offsetX = offset.x();
2625  const double offsetY = offset.y();
2626 
2627  QPointF outputOffset( offsetX, offsetY );
2628 
2629  double angle = mAngle + mLineAngle;
2631  {
2632  context.setOriginalValueVariable( mAngle );
2634  }
2635 
2636  if ( angle )
2637  outputOffset = _rotatedOffset( outputOffset, angle );
2638 
2640 
2641  QString path = mPath;
2643  {
2644  context.setOriginalValueVariable( mPath );
2646  context.renderContext().pathResolver() );
2647  }
2648 
2649  double strokeWidth = mStrokeWidth;
2651  {
2654  }
2656 
2657  QColor fillColor = mColor;
2659  {
2662  }
2663 
2664  QColor strokeColor = mStrokeColor;
2666  {
2669  }
2670 
2672 
2673  const QByteArray &svgContent = QgsApplication::svgCache()->svgContent( path, size, fillColor, strokeColor, strokeWidth,
2675  ( context.renderContext().flags() & Qgis::RenderContextFlag::RenderBlocking ), evaluatedParameters );
2676 
2677  QSvgRenderer r( svgContent );
2678  if ( !r.isValid() )
2679  return false;
2680 
2681  QgsDxfPaintDevice pd( &e );
2682  pd.setDrawingSize( QSizeF( r.defaultSize() ) );
2683 
2684  QSizeF outSize( r.defaultSize() );
2685  outSize.scale( size, size, Qt::KeepAspectRatio );
2686 
2687  QPainter p;
2688  p.begin( &pd );
2689  if ( !qgsDoubleNear( angle, 0.0 ) )
2690  {
2691  p.translate( r.defaultSize().width() / 2.0, r.defaultSize().height() / 2.0 );
2692  p.rotate( angle );
2693  p.translate( -r.defaultSize().width() / 2.0, -r.defaultSize().height() / 2.0 );
2694  }
2695  pd.setShift( shift + QPointF( outputOffset.x(), -outputOffset.y() ) );
2696  pd.setOutputSize( QRectF( -outSize.width() / 2.0, -outSize.height() / 2.0, outSize.width(), outSize.height() ) );
2697  pd.setLayer( layerName );
2698  r.render( &p );
2699  p.end();
2700  return true;
2701 }
2702 
2704 {
2705  bool hasDataDefinedSize = false;
2706  double scaledWidth = calculateSize( context, hasDataDefinedSize );
2707 
2708  bool hasDataDefinedAspectRatio = false;
2709  const double aspectRatio = calculateAspectRatio( context, scaledWidth, hasDataDefinedAspectRatio );
2710  double scaledHeight = scaledWidth * ( !qgsDoubleNear( aspectRatio, 0.0 ) ? aspectRatio : mDefaultAspectRatio );
2711 
2712  scaledWidth = context.renderContext().convertToPainterUnits( scaledWidth, mSizeUnit, mSizeMapUnitScale );
2713  scaledHeight = context.renderContext().convertToPainterUnits( scaledHeight, mSizeUnit, mSizeMapUnitScale );
2714 
2715  //don't render symbols with size below one or above 10,000 pixels
2716  if ( static_cast< int >( scaledWidth ) < 1 || 10000.0 < scaledWidth )
2717  {
2718  return QRectF();
2719  }
2720 
2721  QPointF outputOffset;
2722  double angle = 0.0;
2723  calculateOffsetAndRotation( context, scaledWidth, scaledHeight, outputOffset, angle );
2724 
2725  double strokeWidth = mStrokeWidth;
2727  {
2730  }
2732 
2733  QString path = mPath;
2735  {
2736  context.setOriginalValueVariable( mPath );
2738  context.renderContext().pathResolver() );
2740  {
2741  // need to get colors to take advantage of cached SVGs
2742  QColor fillColor = mColor;
2744  {
2747  }
2748 
2749  const QColor strokeColor = mStrokeColor;
2751  {
2754  }
2755 
2757 
2758  // adjust height of data defined path
2759  const QSizeF svgViewbox = QgsApplication::svgCache()->svgViewboxSize( path, scaledWidth, fillColor, strokeColor, strokeWidth,
2760  context.renderContext().scaleFactor(), aspectRatio,
2761  ( context.renderContext().flags() & Qgis::RenderContextFlag::RenderBlocking ), evaluatedParameters );
2762  scaledHeight = svgViewbox.isValid() ? scaledWidth * svgViewbox.height() / svgViewbox.width() : scaledWidth;
2763  }
2764  }
2765 
2766  QTransform transform;
2767  // move to the desired position
2768  transform.translate( point.x() + outputOffset.x(), point.y() + outputOffset.y() );
2769 
2770  if ( !qgsDoubleNear( angle, 0.0 ) )
2771  transform.rotate( angle );
2772 
2773  //antialiasing
2774  strokeWidth += 1.0 / 2.0;
2775 
2776  QRectF symbolBounds = transform.mapRect( QRectF( -scaledWidth / 2.0,
2777  -scaledHeight / 2.0,
2778  scaledWidth,
2779  scaledHeight ) );
2780 
2781  //extend bounds by pen width / 2.0
2782  symbolBounds.adjust( -strokeWidth / 2.0, -strokeWidth / 2.0,
2783  strokeWidth / 2.0, strokeWidth / 2.0 );
2784 
2785  return symbolBounds;
2786 }
2787 
2789 
2790 QgsRasterMarkerSymbolLayer::QgsRasterMarkerSymbolLayer( const QString &path, double size, double angle, Qgis::ScaleMethod scaleMethod )
2791  : mPath( path )
2792 {
2793  mSize = size;
2794  mAngle = angle;
2795  mOffset = QPointF( 0, 0 );
2798 }
2799 
2801 
2803 {
2804  QString path;
2808 
2809  if ( props.contains( QStringLiteral( "imageFile" ) ) )
2810  path = props[QStringLiteral( "imageFile" )].toString();
2811  if ( props.contains( QStringLiteral( "size" ) ) )
2812  size = props[QStringLiteral( "size" )].toDouble();
2813  if ( props.contains( QStringLiteral( "angle" ) ) )
2814  angle = props[QStringLiteral( "angle" )].toDouble();
2815  if ( props.contains( QStringLiteral( "scale_method" ) ) )
2816  scaleMethod = QgsSymbolLayerUtils::decodeScaleMethod( props[QStringLiteral( "scale_method" )].toString() );
2817 
2818  std::unique_ptr< QgsRasterMarkerSymbolLayer > m = std::make_unique< QgsRasterMarkerSymbolLayer >( path, size, angle, scaleMethod );
2819  m->setCommonProperties( props );
2820  return m.release();
2821 }
2822 
2823 void QgsRasterMarkerSymbolLayer::setCommonProperties( const QVariantMap &properties )
2824 {
2825  if ( properties.contains( QStringLiteral( "alpha" ) ) )
2826  {
2827  setOpacity( properties[QStringLiteral( "alpha" )].toDouble() );
2828  }
2829 
2830  if ( properties.contains( QStringLiteral( "size_unit" ) ) )
2831  setSizeUnit( QgsUnitTypes::decodeRenderUnit( properties[QStringLiteral( "size_unit" )].toString() ) );
2832  if ( properties.contains( QStringLiteral( "size_map_unit_scale" ) ) )
2833  setSizeMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( properties[QStringLiteral( "size_map_unit_scale" )].toString() ) );
2834  if ( properties.contains( QStringLiteral( "fixedAspectRatio" ) ) )
2835  setFixedAspectRatio( properties[QStringLiteral( "fixedAspectRatio" )].toDouble() );
2836 
2837  if ( properties.contains( QStringLiteral( "offset" ) ) )
2838  setOffset( QgsSymbolLayerUtils::decodePoint( properties[QStringLiteral( "offset" )].toString() ) );
2839  if ( properties.contains( QStringLiteral( "offset_unit" ) ) )
2840  setOffsetUnit( QgsUnitTypes::decodeRenderUnit( properties[QStringLiteral( "offset_unit" )].toString() ) );
2841  if ( properties.contains( QStringLiteral( "offset_map_unit_scale" ) ) )
2842  setOffsetMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( properties[QStringLiteral( "offset_map_unit_scale" )].toString() ) );
2843 
2844  if ( properties.contains( QStringLiteral( "horizontal_anchor_point" ) ) )
2845  {
2846  setHorizontalAnchorPoint( QgsMarkerSymbolLayer::HorizontalAnchorPoint( properties[ QStringLiteral( "horizontal_anchor_point" )].toInt() ) );
2847  }
2848  if ( properties.contains( QStringLiteral( "vertical_anchor_point" ) ) )
2849  {
2850  setVerticalAnchorPoint( QgsMarkerSymbolLayer::VerticalAnchorPoint( properties[ QStringLiteral( "vertical_anchor_point" )].toInt() ) );
2851  }
2852 
2855 }
2856 
2857 void QgsRasterMarkerSymbolLayer::resolvePaths( QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving )
2858 {
2859  const QVariantMap::iterator it = properties.find( QStringLiteral( "name" ) );
2860  if ( it != properties.end() && it.value().type() == QVariant::String )
2861  {
2862  if ( saving )
2863  it.value() = QgsSymbolLayerUtils::svgSymbolPathToName( it.value().toString(), pathResolver );
2864  else
2865  it.value() = QgsSymbolLayerUtils::svgSymbolNameToPath( it.value().toString(), pathResolver );
2866  }
2867 }
2868 
2869 void QgsRasterMarkerSymbolLayer::setPath( const QString &path )
2870 {
2871  mPath = path;
2873 }
2874 
2876 {
2877  const bool aPreservedAspectRatio = preservedAspectRatio();
2878  if ( aPreservedAspectRatio && !par )
2879  {
2881  }
2882  else if ( !aPreservedAspectRatio && par )
2883  {
2884  mFixedAspectRatio = 0.0;
2885  }
2886  return preservedAspectRatio();
2887 }
2888 
2890 {
2891  if ( mDefaultAspectRatio == 0.0 )
2892  {
2893  const QSize size = QgsApplication::imageCache()->originalSize( mPath );
2894  mDefaultAspectRatio = ( !size.isNull() && size.isValid() && size.width() > 0 ) ? static_cast< double >( size.height() ) / static_cast< double >( size.width() ) : 0.0;
2895  }
2896  return mDefaultAspectRatio;
2897 }
2898 
2900 {
2901  return QStringLiteral( "RasterMarker" );
2902 }
2903 
2905 {
2906  QPainter *p = context.renderContext().painter();
2907  if ( !p )
2908  return;
2909 
2910  QString path = mPath;
2912  {
2913  context.setOriginalValueVariable( mPath );
2915  }
2916 
2917  if ( path.isEmpty() )
2918  return;
2919 
2920  double width = 0.0;
2921  double height = 0.0;
2922 
2923  bool hasDataDefinedSize = false;
2924  const double scaledSize = calculateSize( context, hasDataDefinedSize );
2925 
2926  bool hasDataDefinedAspectRatio = false;
2927  const double aspectRatio = calculateAspectRatio( context, scaledSize, hasDataDefinedAspectRatio );
2928 
2929  QPointF outputOffset;
2930  double angle = 0.0;
2931 
2932  // RenderPercentage Unit Type takes original image size
2934  {
2935  const QSize size = QgsApplication::imageCache()->originalSize( path );
2936  if ( size.isEmpty() )
2937  return;
2938 
2939  width = ( scaledSize * static_cast< double >( size.width() ) ) / 100.0;
2940  height = ( scaledSize * static_cast< double >( size.height() ) ) / 100.0;
2941 
2942  // don't render symbols with size below one or above 10,000 pixels
2943  if ( static_cast< int >( width ) < 1 || 10000.0 < width || static_cast< int >( height ) < 1 || 10000.0 < height )
2944  return;
2945 
2946  calculateOffsetAndRotation( context, width, height, outputOffset, angle );
2947  }
2948  else
2949  {
2950  width = context.renderContext().convertToPainterUnits( scaledSize, mSizeUnit, mSizeMapUnitScale );
2951  height = width * ( preservedAspectRatio() ? defaultAspectRatio() : aspectRatio );
2952 
2953  if ( preservedAspectRatio() && path != mPath )
2954  {
2955  const QSize size = QgsApplication::imageCache()->originalSize( path );
2956  if ( !size.isNull() && size.isValid() && size.width() > 0 )
2957  {
2958  height = width * ( static_cast< double >( size.height() ) / static_cast< double >( size.width() ) );
2959  }
2960  }
2961 
2962  // don't render symbols with size below one or above 10,000 pixels
2963  if ( static_cast< int >( width ) < 1 || 10000.0 < width )
2964  return;
2965 
2966  calculateOffsetAndRotation( context, scaledSize, scaledSize * ( height / width ), outputOffset, angle );
2967  }
2968 
2969  const QgsScopedQPainterState painterState( p );
2970  p->translate( point + outputOffset );
2971 
2972  const bool rotated = !qgsDoubleNear( angle, 0 );
2973  if ( rotated )
2974  p->rotate( angle );
2975 
2976  double opacity = mOpacity;
2978  {
2981  }
2982  opacity *= context.opacity();
2983 
2984  QImage img = fetchImage( context.renderContext(), path, QSize( width, preservedAspectRatio() ? 0 : width * aspectRatio ), preservedAspectRatio(), opacity );
2985  if ( !img.isNull() )
2986  {
2987  if ( context.selected() )
2988  {
2990  }
2991 
2992  p->drawImage( -img.width() / 2.0, -img.height() / 2.0, img );
2993  }
2994 }
2995 
2996 QImage QgsRasterMarkerSymbolLayer::fetchImage( QgsRenderContext &context, const QString &path, QSize size, bool preserveAspectRatio, double opacity ) const
2997 {
2998  bool cached = false;
2999  return QgsApplication::imageCache()->pathAsImage( path, size, preserveAspectRatio, opacity, cached, context.flags() & Qgis::RenderContextFlag::RenderBlocking );
3000 }
3001 
3002 double QgsRasterMarkerSymbolLayer::calculateSize( QgsSymbolRenderContext &context, bool &hasDataDefinedSize ) const
3003 {
3004  double scaledSize = mSize;
3006 
3007  bool ok = true;
3008  if ( hasDataDefinedSize )
3009  {
3010  context.setOriginalValueVariable( mSize );
3012  }
3013  else
3014  {
3016  if ( hasDataDefinedSize )
3017  {
3018  context.setOriginalValueVariable( mSize );
3020  }
3021  }
3022 
3023  if ( hasDataDefinedSize && ok )
3024  {
3025  switch ( mScaleMethod )
3026  {
3028  scaledSize = std::sqrt( scaledSize );
3029  break;
3031  break;
3032  }
3033  }
3034 
3035  return scaledSize;
3036 }
3037 
3038 double QgsRasterMarkerSymbolLayer::calculateAspectRatio( QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedAspectRatio ) const
3039 {
3041  if ( !hasDataDefinedAspectRatio )
3042  return mFixedAspectRatio;
3043 
3045  return 0.0;
3046 
3047  double scaledAspectRatio = mDefaultAspectRatio;
3048  if ( mFixedAspectRatio > 0.0 )
3049  scaledAspectRatio = mFixedAspectRatio;
3050 
3051  const double defaultHeight = mSize * scaledAspectRatio;
3052  scaledAspectRatio = defaultHeight / scaledSize;
3053 
3054  bool ok = true;
3055  double scaledHeight = scaledSize * scaledAspectRatio;
3057  {
3058  context.setOriginalValueVariable( defaultHeight );
3059  scaledHeight = mDataDefinedProperties.valueAsDouble( QgsSymbolLayer::PropertyHeight, context.renderContext().expressionContext(), defaultHeight, &ok );
3060  }
3061 
3062  if ( hasDataDefinedAspectRatio && ok )
3063  {
3064  switch ( mScaleMethod )
3065  {
3067  scaledHeight = sqrt( scaledHeight );
3068  break;
3070  break;
3071  }
3072  }
3073 
3074  scaledAspectRatio = scaledHeight / scaledSize;
3075 
3076  return scaledAspectRatio;
3077 }
3078 
3079 void QgsRasterMarkerSymbolLayer::calculateOffsetAndRotation( QgsSymbolRenderContext &context, double scaledWidth, double scaledHeight, QPointF &offset, double &angle ) const
3080 {
3081  //offset
3082  double offsetX = 0;
3083  double offsetY = 0;
3084  markerOffset( context, scaledWidth, scaledHeight, offsetX, offsetY );
3085  offset = QPointF( offsetX, offsetY );
3086 
3087  angle = mAngle + mLineAngle;
3089  {
3090  context.setOriginalValueVariable( mAngle );
3092  }
3093 
3095  if ( hasDataDefinedRotation )
3096  {
3097  const QgsFeature *f = context.feature();
3098  if ( f )
3099  {
3100  if ( f->hasGeometry() && f->geometry().type() == QgsWkbTypes::PointGeometry )
3101  {
3102  const QgsMapToPixel &m2p = context.renderContext().mapToPixel();
3103  angle += m2p.mapRotation();
3104  }
3105  }
3106  }
3107 
3108  if ( angle )
3110 }
3111 
3112 
3114 {
3115  QVariantMap map;
3116  map[QStringLiteral( "imageFile" )] = mPath;
3117  map[QStringLiteral( "size" )] = QString::number( mSize );
3118  map[QStringLiteral( "size_unit" )] = QgsUnitTypes::encodeUnit( mSizeUnit );
3119  map[QStringLiteral( "size_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mSizeMapUnitScale );
3120  map[QStringLiteral( "fixedAspectRatio" )] = QString::number( mFixedAspectRatio );
3121  map[QStringLiteral( "angle" )] = QString::number( mAngle );
3122  map[QStringLiteral( "alpha" )] = QString::number( mOpacity );
3123  map[QStringLiteral( "offset" )] = QgsSymbolLayerUtils::encodePoint( mOffset );
3124  map[QStringLiteral( "offset_unit" )] = QgsUnitTypes::encodeUnit( mOffsetUnit );
3125  map[QStringLiteral( "offset_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mOffsetMapUnitScale );
3126  map[QStringLiteral( "scale_method" )] = QgsSymbolLayerUtils::encodeScaleMethod( mScaleMethod );
3127  map[QStringLiteral( "horizontal_anchor_point" )] = QString::number( mHorizontalAnchorPoint );
3128  map[QStringLiteral( "vertical_anchor_point" )] = QString::number( mVerticalAnchorPoint );
3129  return map;
3130 }
3131 
3133 {
3134  std::unique_ptr< QgsRasterMarkerSymbolLayer > m = std::make_unique< QgsRasterMarkerSymbolLayer >( mPath, mSize, mAngle );
3135  copyCommonProperties( m.get() );
3136  return m.release();
3137 }
3138 
3139 
3141 {
3143  other->setOpacity( mOpacity );
3144  other->setOffset( mOffset );
3145  other->setOffsetUnit( mOffsetUnit );
3147  other->setSizeUnit( mSizeUnit );
3151  copyDataDefinedProperties( other );
3152  copyPaintEffect( other );
3153 }
3154 
3156 {
3159 }
3160 
3162 {
3163  return QColor();
3164 }
3165 
3167 {
3169 }
3170 
3172 {
3174 }
3175 
3177 {
3178  bool hasDataDefinedSize = false;
3179  const double scaledSize = calculateSize( context, hasDataDefinedSize );
3180  const double width = context.renderContext().convertToPainterUnits( scaledSize, mSizeUnit, mSizeMapUnitScale );
3181  bool hasDataDefinedAspectRatio = false;
3182  const double aspectRatio = calculateAspectRatio( context, scaledSize, hasDataDefinedAspectRatio );
3183  const double height = width * ( preservedAspectRatio() ? defaultAspectRatio() : aspectRatio );
3184 
3185  //don't render symbols with size below one or above 10,000 pixels
3186  if ( static_cast< int >( scaledSize ) < 1 || 10000.0 < scaledSize )
3187  {
3188  return QRectF();
3189  }
3190 
3191  QPointF outputOffset;
3192  double angle = 0.0;
3193  calculateOffsetAndRotation( context, scaledSize, scaledSize * ( height / width ), outputOffset, angle );
3194 
3195  QTransform transform;
3196 
3197  // move to the desired position
3198  transform.translate( point.x() + outputOffset.x(), point.y() + outputOffset.y() );
3199 
3200  if ( !qgsDoubleNear( angle, 0.0 ) )
3201  transform.rotate( angle );
3202 
3203  QRectF symbolBounds = transform.mapRect( QRectF( -width / 2.0,
3204  -height / 2.0,
3205  width,
3206  height ) );
3207 
3208  return symbolBounds;
3209 }
3210 
3212 
3213 QgsFontMarkerSymbolLayer::QgsFontMarkerSymbolLayer( const QString &fontFamily, QString chr, double pointSize, const QColor &color, double angle )
3214 {
3215  mFontFamily = fontFamily;
3216  mString = chr;
3217  mColor = color;
3218  mAngle = angle;
3219  mSize = pointSize;
3220  mOrigSize = pointSize;
3222  mOffset = QPointF( 0, 0 );
3224  mStrokeColor = DEFAULT_FONTMARKER_BORDERCOLOR;
3225  mStrokeWidth = 0.0;
3226  mStrokeWidthUnit = QgsUnitTypes::RenderMillimeters;
3227  mPenJoinStyle = DEFAULT_FONTMARKER_JOINSTYLE;
3228 }
3229 
3231 
3233 {
3235  QString string = DEFAULT_FONTMARKER_CHR;
3236  double pointSize = DEFAULT_FONTMARKER_SIZE;
3239 
3240  if ( props.contains( QStringLiteral( "font" ) ) )
3241  fontFamily = props[QStringLiteral( "font" )].toString();
3242  if ( props.contains( QStringLiteral( "chr" ) ) && props[QStringLiteral( "chr" )].toString().length() > 0 )
3243  string = props[QStringLiteral( "chr" )].toString();
3244  if ( props.contains( QStringLiteral( "size" ) ) )
3245  pointSize = props[QStringLiteral( "size" )].toDouble();
3246  if ( props.contains( QStringLiteral( "color" ) ) )
3247  color = QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "color" )].toString() );
3248  if ( props.contains( QStringLiteral( "angle" ) ) )
3249  angle = props[QStringLiteral( "angle" )].toDouble();
3250 
3251  QgsFontMarkerSymbolLayer *m = new QgsFontMarkerSymbolLayer( fontFamily, string, pointSize, color, angle );
3252 
3253  if ( props.contains( QStringLiteral( "font_style" ) ) )
3254  m->setFontStyle( props[QStringLiteral( "font_style" )].toString() );
3255  if ( props.contains( QStringLiteral( "outline_color" ) ) )
3256  m->setStrokeColor( QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "outline_color" )].toString() ) );
3257  if ( props.contains( QStringLiteral( "outline_width" ) ) )
3258  m->setStrokeWidth( props[QStringLiteral( "outline_width" )].toDouble() );
3259  if ( props.contains( QStringLiteral( "offset" ) ) )
3260  m->setOffset( QgsSymbolLayerUtils::decodePoint( props[QStringLiteral( "offset" )].toString() ) );
3261  if ( props.contains( QStringLiteral( "offset_unit" ) ) )
3262  m->setOffsetUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "offset_unit" )].toString() ) );
3263  if ( props.contains( QStringLiteral( "offset_map_unit_scale" ) ) )
3264  m->setOffsetMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "offset_map_unit_scale" )].toString() ) );
3265  if ( props.contains( QStringLiteral( "size_unit" ) ) )
3266  m->setSizeUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "size_unit" )].toString() ) );
3267  if ( props.contains( QStringLiteral( "size_map_unit_scale" ) ) )
3268  m->setSizeMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "size_map_unit_scale" )].toString() ) );
3269  if ( props.contains( QStringLiteral( "outline_width_unit" ) ) )
3270  m->setStrokeWidthUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "outline_width_unit" )].toString() ) );
3271  if ( props.contains( QStringLiteral( "outline_width_map_unit_scale" ) ) )
3272  m->setStrokeWidthMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "outline_width_map_unit_scale" )].toString() ) );
3273  if ( props.contains( QStringLiteral( "joinstyle" ) ) )
3274  m->setPenJoinStyle( QgsSymbolLayerUtils::decodePenJoinStyle( props[QStringLiteral( "joinstyle" )].toString() ) );
3275  if ( props.contains( QStringLiteral( "horizontal_anchor_point" ) ) )
3276  m->setHorizontalAnchorPoint( QgsMarkerSymbolLayer::HorizontalAnchorPoint( props[ QStringLiteral( "horizontal_anchor_point" )].toInt() ) );
3277  if ( props.contains( QStringLiteral( "vertical_anchor_point" ) ) )
3278  m->setVerticalAnchorPoint( QgsMarkerSymbolLayer::VerticalAnchorPoint( props[ QStringLiteral( "vertical_anchor_point" )].toInt() ) );
3279 
3280  m->restoreOldDataDefinedProperties( props );
3281 
3282  return m;
3283 }
3284 
3286 {
3287  return QStringLiteral( "FontMarker" );
3288 }
3289 
3291 {
3292  QColor brushColor = mColor;
3293  QColor penColor = mStrokeColor;
3294 
3295  brushColor.setAlphaF( mColor.alphaF() * context.opacity() );
3296  penColor.setAlphaF( mStrokeColor.alphaF() * context.opacity() );
3297 
3298  mBrush = QBrush( brushColor );
3299  mPen = QPen( penColor );
3300  mPen.setJoinStyle( mPenJoinStyle );
3301  mPen.setWidthF( context.renderContext().convertToPainterUnits( mStrokeWidth, mStrokeWidthUnit, mStrokeWidthMapUnitScale ) );
3302 
3303  mFont = QFont( mFontFamily );
3304  if ( !mFontStyle.isEmpty() )
3305  {
3306  mFont.setStyleName( QgsFontUtils::translateNamedStyle( mFontStyle ) );
3307  }
3308 
3309  double sizePixels = context.renderContext().convertToPainterUnits( mSize, mSizeUnit, mSizeMapUnitScale );
3310  mNonZeroFontSize = !qgsDoubleNear( sizePixels, 0.0 );
3311 
3312  if ( mNonZeroFontSize && sizePixels > MAX_FONT_CHARACTER_SIZE_IN_PIXELS )
3313  {
3314  // if font is too large (e.g using map units and map is very zoomed in), then we limit
3315  // the font size and instead scale up the painter.
3316  // this avoids issues with massive font sizes (eg https://github.com/qgis/QGIS/issues/42270)
3317  mFontSizeScale = sizePixels / MAX_FONT_CHARACTER_SIZE_IN_PIXELS;
3318  sizePixels = MAX_FONT_CHARACTER_SIZE_IN_PIXELS;
3319  }
3320  else
3321  mFontSizeScale = 1.0;
3322 
3323  // if a non zero, but small pixel size results, round up to 2 pixels so that a "dot" is at least visible
3324  // (if we set a <=1 pixel size here Qt will reset the font to a default size, leading to much too large symbols)
3325  mFont.setPixelSize( std::max( 2, static_cast< int >( std::round( sizePixels ) ) ) );
3326  mFontMetrics.reset( new QFontMetrics( mFont ) );
3327  mChrWidth = mFontMetrics->horizontalAdvance( mString );
3328  mChrOffset = QPointF( mChrWidth / 2.0, -mFontMetrics->ascent() / 2.0 );
3329  mOrigSize = mSize; // save in case the size would be data defined
3330 
3331  // use caching only when not using a data defined character
3335  if ( mUseCachedPath )
3336  {
3337  QPointF chrOffset = mChrOffset;
3338  double chrWidth;
3339  const QString charToRender = characterToRender( context, chrOffset, chrWidth );
3340  mCachedPath = QPainterPath();
3341  mCachedPath.addText( -chrOffset.x(), -chrOffset.y(), mFont, charToRender );
3342  }
3343 }
3344 
3346 {
3347  Q_UNUSED( context )
3348 }
3349 
3350 QString QgsFontMarkerSymbolLayer::characterToRender( QgsSymbolRenderContext &context, QPointF &charOffset, double &charWidth )
3351 {
3352  charOffset = mChrOffset;
3353  QString stringToRender = mString;
3355  {
3356  context.setOriginalValueVariable( mString );
3358  if ( stringToRender != mString )
3359  {
3360  charWidth = mFontMetrics->horizontalAdvance( stringToRender );
3361  charOffset = QPointF( charWidth / 2.0, -mFontMetrics->ascent() / 2.0 );
3362  }
3363  }
3364  return stringToRender;
3365 }
3366 
3367 void QgsFontMarkerSymbolLayer::calculateOffsetAndRotation( QgsSymbolRenderContext &context,
3368  double scaledSize,
3369  bool &hasDataDefinedRotation,
3370  QPointF &offset,
3371  double &angle ) const
3372 {
3373  //offset
3374  double offsetX = 0;
3375  double offsetY = 0;
3376  markerOffset( context, scaledSize, scaledSize, offsetX, offsetY );
3377  offset = QPointF( offsetX, offsetY );
3378 
3379  //angle
3380  bool ok = true;
3381  angle = mAngle + mLineAngle;
3383  {
3384  context.setOriginalValueVariable( angle );
3386 
3387  // If the expression evaluation was not successful, fallback to static value
3388  if ( !ok )
3389  angle = mAngle + mLineAngle;
3390  }
3391 
3392  hasDataDefinedRotation = context.renderHints() & Qgis::SymbolRenderHint::DynamicRotation;
3393  if ( hasDataDefinedRotation )
3394  {
3395  // For non-point markers, "dataDefinedRotation" means following the
3396  // shape (shape-data defined). For them, "field-data defined" does
3397  // not work at all. TODO: if "field-data defined" ever gets implemented
3398  // we'll need a way to distinguish here between the two, possibly
3399  // using another flag in renderHints()
3400  const QgsFeature *f = context.feature();
3401  if ( f )
3402  {
3403  if ( f->hasGeometry() && f->geometry().type() == QgsWkbTypes::PointGeometry )
3404  {
3405  const QgsMapToPixel &m2p = context.renderContext().mapToPixel();
3406  angle += m2p.mapRotation();
3407  }
3408  }
3409  }
3410 
3411  if ( angle )
3413 }
3414 
3415 double QgsFontMarkerSymbolLayer::calculateSize( QgsSymbolRenderContext &context )
3416 {
3417  double scaledSize = mSize;
3418  const bool hasDataDefinedSize = mDataDefinedProperties.isActive( QgsSymbolLayer::PropertySize );
3419 
3420  bool ok = true;
3421  if ( hasDataDefinedSize )
3422  {
3423  context.setOriginalValueVariable( mSize );
3425  }
3426 
3427  if ( hasDataDefinedSize && ok )
3428  {
3429  switch ( mScaleMethod )
3430  {
3432  scaledSize = std::sqrt( scaledSize );
3433  break;
3435  break;
3436  }
3437  }
3438  return scaledSize;
3439 }
3440 
3442 {
3443  QPainter *p = context.renderContext().painter();
3444  if ( !p || !mNonZeroFontSize )
3445  return;
3446 
3447  QTransform transform;
3448 
3449  bool ok;
3450  QColor brushColor = mColor;
3452  {
3455  }
3456  brushColor = context.selected() ? context.renderContext().selectionColor() : brushColor;
3457  if ( !context.selected() || !SELECTION_IS_OPAQUE )
3458  {
3459  brushColor.setAlphaF( brushColor.alphaF() * context.opacity() );
3460  }
3461  mBrush.setColor( brushColor );
3462 
3463  QColor penColor = mStrokeColor;
3465  {
3468  }
3469  penColor.setAlphaF( penColor.alphaF() * context.opacity() );
3470 
3471  double penWidth = context.renderContext().convertToPainterUnits( mStrokeWidth, mStrokeWidthUnit, mStrokeWidthMapUnitScale );
3473  {
3474  context.setOriginalValueVariable( mStrokeWidth );
3476  if ( ok )
3477  {
3478  penWidth = context.renderContext().convertToPainterUnits( strokeWidth, mStrokeWidthUnit, mStrokeWidthMapUnitScale );
3479  }
3480  }
3481 
3483  {
3485  const QString style = mDataDefinedProperties.valueAsString( QgsSymbolLayer::PropertyJoinStyle, context.renderContext().expressionContext(), QString(), &ok );
3486  if ( ok )
3487  {
3488  mPen.setJoinStyle( QgsSymbolLayerUtils::decodePenJoinStyle( style ) );
3489  }
3490  }
3491 
3492  const QgsScopedQPainterState painterState( p );
3493  p->setBrush( mBrush );
3494  if ( !qgsDoubleNear( penWidth, 0.0 ) )
3495  {
3496  mPen.setColor( penColor );
3497  mPen.setWidthF( penWidth );
3498  p->setPen( mPen );
3499  }
3500  else
3501  {
3502  p->setPen( Qt::NoPen );
3503  }
3504 
3506  {
3507  context.setOriginalValueVariable( mFontFamily );
3509  mFont.setFamily( ok ? fontFamily : mFontFamily );
3510  }
3512  {
3513  context.setOriginalValueVariable( mFontStyle );
3516  }
3518  {
3519  mFontMetrics.reset( new QFontMetrics( mFont ) );
3520  }
3521 
3522  QPointF chrOffset = mChrOffset;
3523  double chrWidth;
3524  const QString charToRender = characterToRender( context, chrOffset, chrWidth );
3525 
3526  const double sizeToRender = calculateSize( context );
3527 
3528  bool hasDataDefinedRotation = false;
3529  QPointF offset;
3530  double angle = 0;
3531  calculateOffsetAndRotation( context, sizeToRender, hasDataDefinedRotation, offset, angle );
3532 
3533  p->translate( point.x() + offset.x(), point.y() + offset.y() );
3534 
3535  if ( !qgsDoubleNear( angle, 0.0 ) )
3536  transform.rotate( angle );
3537 
3538  if ( !qgsDoubleNear( sizeToRender, mOrigSize ) )
3539  {
3540  const double s = sizeToRender / mOrigSize;
3541  transform.scale( s, s );
3542  }
3543 
3544  if ( !qgsDoubleNear( mFontSizeScale, 1.0 ) )
3545  transform.scale( mFontSizeScale, mFontSizeScale );
3546 
3547  if ( mUseCachedPath )
3548  {
3549  p->drawPath( transform.map( mCachedPath ) );
3550  }
3551  else
3552  {
3553  QPainterPath path;
3554  path.addText( -chrOffset.x(), -chrOffset.y(), mFont, charToRender );
3555  p->drawPath( transform.map( path ) );
3556  }
3557 }
3558 
3560 {
3561  QVariantMap props;
3562  props[QStringLiteral( "font" )] = mFontFamily;
3563  props[QStringLiteral( "font_style" )] = mFontStyle;
3564  props[QStringLiteral( "chr" )] = mString;
3565  props[QStringLiteral( "size" )] = QString::number( mSize );
3566  props[QStringLiteral( "size_unit" )] = QgsUnitTypes::encodeUnit( mSizeUnit );
3567  props[QStringLiteral( "size_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mSizeMapUnitScale );
3568  props[QStringLiteral( "color" )] = QgsSymbolLayerUtils::encodeColor( mColor );
3569  props[QStringLiteral( "outline_color" )] = QgsSymbolLayerUtils::encodeColor( mStrokeColor );
3570  props[QStringLiteral( "outline_width" )] = QString::number( mStrokeWidth );
3571  props[QStringLiteral( "outline_width_unit" )] = QgsUnitTypes::encodeUnit( mStrokeWidthUnit );
3572  props[QStringLiteral( "outline_width_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mStrokeWidthMapUnitScale );
3573  props[QStringLiteral( "joinstyle" )] = QgsSymbolLayerUtils::encodePenJoinStyle( mPenJoinStyle );
3574  props[QStringLiteral( "angle" )] = QString::number( mAngle );
3575  props[QStringLiteral( "offset" )] = QgsSymbolLayerUtils::encodePoint( mOffset );
3576  props[QStringLiteral( "offset_unit" )] = QgsUnitTypes::encodeUnit( mOffsetUnit );
3577  props[QStringLiteral( "offset_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mOffsetMapUnitScale );
3578  props[QStringLiteral( "horizontal_anchor_point" )] = QString::number( mHorizontalAnchorPoint );
3579  props[QStringLiteral( "vertical_anchor_point" )] = QString::number( mVerticalAnchorPoint );
3580  return props;
3581 }
3582 
3584 {
3585  QgsFontMarkerSymbolLayer *m = new QgsFontMarkerSymbolLayer( mFontFamily, mString, mSize, mColor, mAngle );
3586  m->setFontStyle( mFontStyle );
3587  m->setStrokeColor( mStrokeColor );
3588  m->setStrokeWidth( mStrokeWidth );
3589  m->setStrokeWidthUnit( mStrokeWidthUnit );
3590  m->setStrokeWidthMapUnitScale( mStrokeWidthMapUnitScale );
3591  m->setPenJoinStyle( mPenJoinStyle );
3592  m->setOffset( mOffset );
3593  m->setOffsetUnit( mOffsetUnit );
3595  m->setSizeUnit( mSizeUnit );
3600  copyPaintEffect( m );
3601  return m;
3602 }
3603 
3604 void QgsFontMarkerSymbolLayer::writeSldMarker( QDomDocument &doc, QDomElement &element, const QVariantMap &props ) const
3605 {
3606  // <Graphic>
3607  QDomElement graphicElem = doc.createElement( QStringLiteral( "se:Graphic" ) );
3608  element.appendChild( graphicElem );
3609 
3610  const QString fontPath = QStringLiteral( "ttf://%1" ).arg( mFontFamily );
3611  int markIndex = !mString.isEmpty() ? mString.at( 0 ).unicode() : 0;
3612  const double size = QgsSymbolLayerUtils::rescaleUom( mSize, mSizeUnit, props );
3613  QgsSymbolLayerUtils::externalMarkerToSld( doc, graphicElem, fontPath, QStringLiteral( "ttf" ), &markIndex, mColor, size );
3614 
3615  // <Rotation>
3616  QString angleFunc;
3617  bool ok;
3618  const double angle = props.value( QStringLiteral( "angle" ), QStringLiteral( "0" ) ).toDouble( &ok );
3619  if ( !ok )
3620  {
3621  angleFunc = QStringLiteral( "%1 + %2" ).arg( props.value( QStringLiteral( "angle" ), QStringLiteral( "0" ) ).toString() ).arg( mAngle );
3622  }
3623  else if ( !qgsDoubleNear( angle + mAngle, 0.0 ) )
3624  {
3625  angleFunc = QString::number( angle + mAngle );
3626  }
3627  QgsSymbolLayerUtils::createRotationElement( doc, graphicElem, angleFunc );
3628 
3629  // <Displacement>
3630  const QPointF offset = QgsSymbolLayerUtils::rescaleUom( mOffset, mOffsetUnit, props );
3632 }
3633 
3635 {
3637  || mStrokeWidthUnit == QgsUnitTypes::RenderMapUnits || mStrokeWidthUnit == QgsUnitTypes::RenderMetersInMapUnits
3639 }
3640 
3642 {
3644  mStrokeWidthUnit = unit;
3645 }
3646 
3648 {
3649  QPointF chrOffset = mChrOffset;
3650  double chrWidth = mChrWidth;
3651  //calculate width of rendered character
3652  ( void )characterToRender( context, chrOffset, chrWidth );
3653 
3654  if ( !mFontMetrics )
3655  mFontMetrics.reset( new QFontMetrics( mFont ) );
3656 
3657  double scaledSize = calculateSize( context );
3658  if ( !qgsDoubleNear( scaledSize, mOrigSize ) )
3659  {
3660  chrWidth *= scaledSize / mOrigSize;
3661  }
3662  chrWidth *= mFontSizeScale;
3663 
3664  bool hasDataDefinedRotation = false;
3665  QPointF offset;
3666  double angle = 0;
3667  calculateOffsetAndRotation( context, scaledSize, hasDataDefinedRotation, offset, angle );
3668  scaledSize = context.renderContext().convertToPainterUnits( scaledSize, mSizeUnit, mSizeMapUnitScale );
3669 
3670  QTransform transform;
3671 
3672  // move to the desired position
3673  transform.translate( point.x() + offset.x(), point.y() + offset.y() );
3674 
3675  if ( !qgsDoubleNear( angle, 0.0 ) )
3676  transform.rotate( angle );
3677 
3678  QRectF symbolBounds = transform.mapRect( QRectF( -chrWidth / 2.0,
3679  -scaledSize / 2.0,
3680  chrWidth,
3681  scaledSize ) );
3682  return symbolBounds;
3683 }
3684 
3686 {
3687  QgsDebugMsgLevel( QStringLiteral( "Entered." ), 4 );
3688 
3689  QDomElement graphicElem = element.firstChildElement( QStringLiteral( "Graphic" ) );
3690  if ( graphicElem.isNull() )
3691  return nullptr;
3692 
3693  QString name, format;
3694  QColor color;
3695  double size;
3696  int chr;
3697 
3698  if ( !QgsSymbolLayerUtils::externalMarkerFromSld( graphicElem, name, format, chr, color, size ) )
3699  return nullptr;
3700 
3701  if ( !name.startsWith( QLatin1String( "ttf://" ) ) || format != QLatin1String( "ttf" ) )
3702  return nullptr;
3703 
3704  const QString fontFamily = name.mid( 6 );
3705 
3706  double angle = 0.0;
3707  QString angleFunc;
3708  if ( QgsSymbolLayerUtils::rotationFromSldElement( graphicElem, angleFunc ) )
3709  {
3710  bool ok;
3711  const double d = angleFunc.toDouble( &ok );
3712  if ( ok )
3713  angle = d;
3714  }
3715 
3716  QPointF offset;
3718 
3719  double scaleFactor = 1.0;
3720  const QString uom = element.attribute( QStringLiteral( "uom" ) );
3721  QgsUnitTypes::RenderUnit sldUnitSize = QgsSymbolLayerUtils::decodeSldUom( uom, &scaleFactor );
3722  offset.setX( offset.x() * scaleFactor );
3723  offset.setY( offset.y() * scaleFactor );
3724  size = size * scaleFactor;
3725 
3727  m->setOutputUnit( sldUnitSize );
3728  m->setAngle( angle );
3729  m->setOffset( offset );
3730  return m;
3731 }
3732 
3733 void QgsFontMarkerSymbolLayer::resolveFonts( const QVariantMap &properties, const QgsReadWriteContext &context )
3734 {
3735  const QString fontFamily = properties.value( QStringLiteral( "font" ), DEFAULT_FONTMARKER_FONT ).toString();
3737  {
3738  context.pushMessage( QObject::tr( "Font “%1” not available on system" ).arg( fontFamily ) );
3739  }
3740 }
3741 
3743 {
3744  QMap<QString, QgsProperty>::iterator it = mParameters.begin();
3745  for ( ; it != mParameters.end(); ++it )
3746  it.value().prepare( context.renderContext().expressionContext() );
3747 
3749 }
3750 
3751 
3752 QSet<QString> QgsSvgMarkerSymbolLayer::usedAttributes( const QgsRenderContext &context ) const
3753 {
3754  QSet<QString> attrs = QgsMarkerSymbolLayer::usedAttributes( context );
3755 
3756  QMap<QString, QgsProperty>::const_iterator it = mParameters.constBegin();
3757  for ( ; it != mParameters.constEnd(); ++it )
3758  {
3759  attrs.unite( it.value().referencedFields( context.expressionContext(), true ) );
3760  }
3761 
3762  return attrs;
3763 }
3764 
3765 //
3766 // QgsAnimatedMarkerSymbolLayer
3767 //
3768 
3769 QgsAnimatedMarkerSymbolLayer::QgsAnimatedMarkerSymbolLayer( const QString &path, double size, double angle )
3770  : QgsRasterMarkerSymbolLayer( path, size, angle )
3771 {
3772 
3773 }
3774 
3776 
3777 QgsSymbolLayer *QgsAnimatedMarkerSymbolLayer::create( const QVariantMap &properties )
3778 {
3779  QString path;
3782 
3783  if ( properties.contains( QStringLiteral( "imageFile" ) ) )
3784  path = properties[QStringLiteral( "imageFile" )].toString();
3785  if ( properties.contains( QStringLiteral( "size" ) ) )
3786  size = properties[QStringLiteral( "size" )].toDouble();
3787  if ( properties.contains( QStringLiteral( "angle" ) ) )
3788  angle = properties[QStringLiteral( "angle" )].toDouble();
3789 
3790  std::unique_ptr< QgsAnimatedMarkerSymbolLayer > m = std::make_unique< QgsAnimatedMarkerSymbolLayer >( path, size, angle );
3791  m->setFrameRate( properties.value( QStringLiteral( "frameRate" ), QStringLiteral( "10" ) ).toDouble() );
3792 
3793  m->setCommonProperties( properties );
3794  return m.release();
3795 }
3796 
3798 {
3799  return QStringLiteral( "AnimatedMarker" );
3800 }
3801 
3803 {
3804  QVariantMap res = QgsRasterMarkerSymbolLayer::properties();
3805  res.insert( QStringLiteral( "frameRate" ), mFrameRateFps );
3806  return res;
3807 }
3808 
3810 {
3811  std::unique_ptr< QgsAnimatedMarkerSymbolLayer > m = std::make_unique< QgsAnimatedMarkerSymbolLayer >( mPath, mSize, mAngle );
3812  m->setFrameRate( mFrameRateFps );
3813  copyCommonProperties( m.get() );
3814  return m.release();
3815 }
3816 
3818 {
3820 
3821  mPreparedPaths.clear();
3823  {
3825  mStaticPath = true;
3826  }
3827  else
3828  {
3829  mStaticPath = false;
3830  }
3831 }
3832 
3833 QImage QgsAnimatedMarkerSymbolLayer::fetchImage( QgsRenderContext &context, const QString &path, QSize size, bool preserveAspectRatio, double opacity ) const
3834 {
3835  if ( !mStaticPath && !mPreparedPaths.contains( path ) )
3836  {
3838  mPreparedPaths.insert( path );
3839  }
3840 
3841  const long long mapFrameNumber = context.currentFrame();
3842  const int totalFrameCount = QgsApplication::imageCache()->totalFrameCount( path, context.flags() & Qgis::RenderContextFlag::RenderBlocking );
3843  const double markerAnimationDuration = totalFrameCount / mFrameRateFps;
3844 
3845  double animationTimeSeconds = 0;
3846  if ( mapFrameNumber >= 0 && context.frameRate() > 0 )
3847  {
3848  // render is part of an animation, so we base the calculated frame on that
3849  animationTimeSeconds = mapFrameNumber / context.frameRate();
3850  }
3851  else
3852  {
3853  // render is outside of animation, so base the calculated frame on the current epoch
3854  animationTimeSeconds = QDateTime::currentMSecsSinceEpoch() / 1000.0;
3855  }
3856 
3857  const double markerAnimationProgressSeconds = std::fmod( animationTimeSeconds, markerAnimationDuration );
3858  const int movieFrame = static_cast< int >( std::floor( markerAnimationProgressSeconds * mFrameRateFps ) );
3859 
3860  bool cached = false;
3861  return QgsApplication::imageCache()->pathAsImage( path, size, preserveAspectRatio, opacity, cached, context.flags() & Qgis::RenderContextFlag::RenderBlocking, 96, movieFrame );
3862 }
3863 
QgsSimpleMarkerSymbolLayerBase::availableShapes
static QList< Qgis::MarkerShape > availableShapes()
Returns a list of all available shape types.
Definition: qgsmarkersymbollayer.cpp:64
QgsSymbolRenderContext::setOriginalValueVariable
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for data defined symbology.
Definition: qgssymbolrendercontext.cpp:36
QgsAnimatedMarkerSymbolLayer::clone
QgsAnimatedMarkerSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
Definition: qgsmarkersymbollayer.cpp:3809
QgsFilledMarkerSymbolLayer::setColor
void setColor(const QColor &c) override
Sets the "representative" color for the symbol layer.
Definition: qgsmarkersymbollayer.cpp:1875
qt_defaultDpiX
Q_GUI_EXPORT int qt_defaultDpiX()
QgsRasterMarkerSymbolLayer::defaultAspectRatio
double defaultAspectRatio() const
Returns the default marker aspect ratio between width and height, 0 if not yet calculated.
Definition: qgsmarkersymbollayer.h:762
QgsRasterMarkerSymbolLayer::mFixedAspectRatio
double mFixedAspectRatio
The marker fixed aspect ratio.
Definition: qgsmarkersymbollayer.h:834
QgsFilledMarkerSymbolLayer::create
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsFilledMarkerSymbolLayer.
Definition: qgsmarkersymbollayer.cpp:1733
QgsMarkerSymbolLayer::setSizeUnit
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the symbol's size.
Definition: qgssymbollayer.h:794
qgssvgcache.h
QgsSvgMarkerSymbolLayer::mapUnitScale
QgsMapUnitScale mapUnitScale() const override
Definition: qgsmarkersymbollayer.cpp:2496
Qgis::RenderContextFlag::RenderSymbolPreview
@ RenderSymbolPreview
The render is for a symbol preview only and map based properties may not be available,...
QgsSvgMarkerSymbolLayer::layerType
QString layerType() const override
Returns a string that represents this layer type.
Definition: qgsmarkersymbollayer.cpp:2161
QgsAbstractPropertyCollection::valueAsDouble
double valueAsDouble(int key, const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a double.
Definition: qgspropertycollection.cpp:66
QgsProperty::variantMapToPropertyMap
static QMap< QString, QgsProperty > variantMapToPropertyMap(const QVariantMap &variantMap)
Convert a map of QVariant to a map of QgsProperty This is useful to restore a map of properties.
Definition: qgsproperty.cpp:217
QgsSymbolLayerUtils::encodeColor
static QString encodeColor(const QColor &color)
Definition: qgssymbollayerutils.cpp:64
QgsMarkerSymbolLayer::setHorizontalAnchorPoint
void setHorizontalAnchorPoint(HorizontalAnchorPoint h)
Sets the horizontal anchor point for positioning the symbol.
Definition: qgssymbollayer.h:894
QgsMarkerSymbolLayer::VerticalAnchorPoint
VerticalAnchorPoint
Symbol vertical anchor points.
Definition: qgssymbollayer.h:718
QgsRasterMarkerSymbolLayer::renderPoint
void renderPoint(QPointF point, QgsSymbolRenderContext &context) override
Renders a marker at the specified point.
Definition: qgsmarkersymbollayer.cpp:2904
Qgis::MarkerShape::ArrowHead
@ ArrowHead
Right facing arrow head (unfilled, lines only)
QgsSymbolLayer::mColor
QColor mColor
Definition: qgssymbollayer.h:648
QgsRenderContext::setPainterFlagsUsingContext
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
Definition: qgsrendercontext.cpp:169
Qgis::MarkerShape::QuarterArc
@ QuarterArc
A line-only one quarter arc (since QGIS 3.20)
Qgis::MarkerShape::SemiCircle
@ SemiCircle
Semi circle (top half)
QgsFilledMarkerSymbolLayer
Filled marker symbol layer, consisting of a shape which is rendered using a QgsFillSymbol....
Definition: qgsmarkersymbollayer.h:435
QgsRenderContext::mapToPixel
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
Definition: qgsrendercontext.h:258
QgsSvgMarkerSymbolLayer::usedAttributes
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
Definition: qgsmarkersymbollayer.cpp:3752
QgsSimpleMarkerSymbolLayer::setStrokeWidthMapUnitScale
void setStrokeWidthMapUnitScale(const QgsMapUnitScale &scale)
Sets the map scale for the width of the marker's stroke.
Definition: qgsmarkersymbollayer.h:357
QgsImageCache::originalSize
QSize originalSize(const QString &path, bool blocking=false) const
Returns the original size (in pixels) of the image at the specified path.
Definition: qgsimagecache.cpp:208
Qgis::MarkerShape::DiagonalHalfSquare
@ DiagonalHalfSquare
Diagonal half square (bottom left half)
QgsMarkerSymbolLayer::size
double size() const
Returns the symbol size.
Definition: qgssymbollayer.h:785
QgsSymbolLayer::setColor
virtual void setColor(const QColor &color)
Sets the "representative" color for the symbol layer.
Definition: qgssymbollayer.cpp:252
DEFAULT_SIMPLEMARKER_ANGLE
#define DEFAULT_SIMPLEMARKER_ANGLE
Definition: qgsmarkersymbollayer.h:28
QgsFontMarkerSymbolLayer::properties
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
Definition: qgsmarkersymbollayer.cpp:3559
QgsSvgMarkerSymbolLayer::bounds
QRectF bounds(QPointF point, QgsSymbolRenderContext &context) override
Returns the approximate bounding box of the marker symbol layer, taking into account any data defined...
Definition: qgsmarkersymbollayer.cpp:2703
QgsRasterMarkerSymbolLayer::opacity
double opacity() const
Returns the marker opacity.
Definition: qgsmarkersymbollayer.h:749
QgsUnitTypes::RenderUnit
RenderUnit
Rendering size units.
Definition: qgsunittypes.h:167
QgsSimpleMarkerSymbolLayer::strokeStyle
Qt::PenStyle strokeStyle() const
Returns the marker's stroke style (e.g., solid, dashed, etc)
Definition: qgsmarkersymbollayer.h:263
QgsSvgMarkerSymbolLayer::mDefaultAspectRatio
double mDefaultAspectRatio
The marker default aspect ratio.
Definition: qgsmarkersymbollayer.h:656
QgsSimpleMarkerSymbolLayer::renderPoint
void renderPoint(QPointF point, QgsSymbolRenderContext &context) override
Renders a marker at the specified point.
Definition: qgsmarkersymbollayer.cpp:1193
QgsDxfExport
Exports QGIS layers to the DXF format.
Definition: qgsdxfexport.h:64
QgsMarkerSymbolLayer::mSizeMapUnitScale
QgsMapUnitScale mSizeMapUnitScale
Marker size map unit scale.
Definition: qgssymbollayer.h:997
Qgis::SymbolType::Fill
@ Fill
Fill symbol.
QgsImageCache::pathAsImage
QImage pathAsImage(const QString &path, const QSize size, const bool keepAspectRatio, const double opacity, bool &fitsInCache, bool blocking=false, double targetDpi=96, int frameNumber=-1, bool *isMissing=nullptr)
Returns the specified path rendered as an image.
Definition: qgsimagecache.cpp:137
QgsFontMarkerSymbolLayer::setStrokeWidth
void setStrokeWidth(double width)
Set's the marker's stroke width.
Definition: qgsmarkersymbollayer.h:980
QgsSimpleMarkerSymbolLayer::penJoinStyle
Qt::PenJoinStyle penJoinStyle() const
Returns the marker's stroke join style (e.g., miter, bevel, etc).
Definition: qgsmarkersymbollayer.h:283
QgsSvgMarkerSymbolLayer::setOutputUnit
void setOutputUnit(QgsUnitTypes::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
Definition: qgsmarkersymbollayer.cpp:2474
QgsRenderContext::expressionContext
QgsExpressionContext & expressionContext()
Gets the expression context.
Definition: qgsrendercontext.h:625
QgsFilledMarkerSymbolLayer::usedAttributes
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
Definition: qgsmarkersymbollayer.cpp:1858
QgsMapToPixel::mapUnitsPerPixel
double mapUnitsPerPixel() const
Returns the current map units per pixel.
Definition: qgsmaptopixel.h:229
QgsSymbolLayerUtils::externalGraphicFromSld
static bool externalGraphicFromSld(QDomElement &element, QString &path, QString &mime, QColor &color, double &size)
Definition: qgssymbollayerutils.cpp:2525
QgsFontMarkerSymbolLayer::usesMapUnits
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
Definition: qgsmarkersymbollayer.cpp:3634
QgsSimpleMarkerSymbolLayerBase::shapeToPolygon
bool shapeToPolygon(Qgis::MarkerShape shape, QPolygonF &polygon) const
Creates a polygon representing the specified shape.
Definition: qgsmarkersymbollayer.cpp:454
DEFAULT_SIMPLEMARKER_NAME
#define DEFAULT_SIMPLEMARKER_NAME
Definition: qgsmarkersymbollayer.h:23
QgsReadWriteContext
The class is used as a container of context for various read/write operations on other objects.
Definition: qgsreadwritecontext.h:34
QgsSymbolLayerUtils::wellKnownMarkerFromSld
static bool wellKnownMarkerFromSld(QDomElement &element, QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle, double &strokeWidth, double &size)
Definition: qgssymbollayerutils.cpp:2660
QgsMarkerSymbolLayer::mapUnitScale
QgsMapUnitScale mapUnitScale() const override
Definition: qgssymbollayer.cpp:712
QgsRasterMarkerSymbolLayer::usesMapUnits
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
Definition: qgsmarkersymbollayer.cpp:3155
QgsFontMarkerSymbolLayer::QgsFontMarkerSymbolLayer
QgsFontMarkerSymbolLayer(const QString &fontFamily=DEFAULT_FONTMARKER_FONT, QString chr=DEFAULT_FONTMARKER_CHR, double pointSize=DEFAULT_FONTMARKER_SIZE, const QColor &color=DEFAULT_FONTMARKER_COLOR, double angle=DEFAULT_FONTMARKER_ANGLE)
Constructs a font marker symbol layer.
Definition: qgsmarkersymbollayer.cpp:3213
Qgis::MarkerShape::CrossFill
@ CrossFill
Solid filled cross.
QgsSymbolLayerUtils::encodeMapUnitScale
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
Definition: qgssymbollayerutils.cpp:666
QgsPoint
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:48
QgsDxfExport::writePolygon
void writePolygon(const QgsRingSequence &polygon, const QString &layer, const QString &hatchPattern, const QColor &color)
Draw dxf filled polygon (HATCH)
Definition: qgsdxfexport.cpp:1183
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QgsSymbolRenderContext::feature
const QgsFeature * feature() const
Returns the current feature being rendered.
Definition: qgssymbolrendercontext.h:143
qgsexpression.h
QgsDxfPaintDevice::setDrawingSize
void setDrawingSize(QSizeF size)
Definition: qgsdxfpaintdevice.h:45
QgsSymbolLayer::prepareExpressions
virtual void prepareExpressions(const QgsSymbolRenderContext &context)
Prepares all data defined property expressions for evaluation.
Definition: qgssymbollayer.cpp:276
QgsAnimatedMarkerSymbolLayer::create
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates an animated marker symbol layer from a string map of properties.
Definition: qgsmarkersymbollayer.cpp:3777
QgsSimpleMarkerSymbolLayer::setOutputUnit
void setOutputUnit(QgsUnitTypes::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
Definition: qgsmarkersymbollayer.cpp:1618
QgsSimpleMarkerSymbolLayer::mPenJoinStyle
Qt::PenJoinStyle mPenJoinStyle
Stroke pen join style.
Definition: qgsmarkersymbollayer.h:394
QgsSymbolLayerUtils::externalMarkerFromSld
static bool externalMarkerFromSld(QDomElement &element, QString &path, QString &format, int &markIndex, QColor &color, double &size)
Definition: qgssymbollayerutils.cpp:2580
Qgis::MarkerShape::ArrowHeadFilled
@ ArrowHeadFilled
Right facing filled arrow head.
QgsSimpleMarkerSymbolLayerBase::mShape
Qgis::MarkerShape mShape
Symbol shape.
Definition: qgsmarkersymbollayer.h:156
QgsSymbolLayer::PropertyFontFamily
@ PropertyFontFamily
Font family.
Definition: qgssymbollayer.h:201
Qgis::MarkerShape::AsteriskFill
@ AsteriskFill
A filled asterisk shape (since QGIS 3.18)
QgsSvgCache::svgContent
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.
Definition: qgssvgcache.cpp:209
Qgis::MarkerShape::Hexagon
@ Hexagon
Hexagon.
QgsSimpleMarkerSymbolLayer::mSelCache
QImage mSelCache
Cached image of selected marker, if using cached version.
Definition: qgsmarkersymbollayer.h:409
Qgis::MarkerShape::Cross2
@ Cross2
Rotated cross (lines only), 'x' shape.
QgsSymbolLayer::PropertyFillColor
@ PropertyFillColor
Fill color.
Definition: qgssymbollayer.h:147
QgsSimpleMarkerSymbolLayerBase::startRender
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
Definition: qgsmarkersymbollayer.cpp:153
Qgis::MarkerShape::Arrow
@ Arrow
Arrow.
DEFAULT_FONTMARKER_ANGLE
#define DEFAULT_FONTMARKER_ANGLE
Definition: qgsmarkersymbollayer.h:854
qgssymbollayerutils.h
QgsFilledMarkerSymbolLayer::estimateMaxBleed
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
Definition: qgsmarkersymbollayer.cpp:1849
QgsMarkerSymbolLayer::setAngle
void setAngle(double angle)
Sets the rotation angle for the marker.
Definition: qgssymbollayer.h:751
QgsSymbolRenderContext::opacity
qreal opacity() const
Returns the opacity for the symbol.
Definition: qgssymbolrendercontext.h:105
QgsSymbolLayerUtils::encodePenCapStyle
static QString encodePenCapStyle(Qt::PenCapStyle style)
Definition: qgssymbollayerutils.cpp:235
QgsRasterMarkerSymbolLayer::updateDefaultAspectRatio
double updateDefaultAspectRatio()
Calculates the default marker aspect ratio between width and height.
Definition: qgsmarkersymbollayer.cpp:2889
QgsSvgMarkerSymbolLayer::setPath
void setPath(const QString &path)
Set the marker SVG path.
Definition: qgsmarkersymbollayer.cpp:2078
QgsSymbolLayer::hasDataDefinedProperties
virtual bool hasDataDefinedProperties() const
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
Definition: qgssymbollayer.cpp:287
QgsRenderContext::flags
Qgis::RenderContextFlags flags() const
Returns combination of flags used for rendering.
Definition: qgsrendercontext.cpp:224
qgsmarkersymbollayer.h
Qgis::MarkerShape::Square
@ Square
Square.
QgsFilledMarkerSymbolLayer::QgsFilledMarkerSymbolLayer
QgsFilledMarkerSymbolLayer(Qgis::MarkerShape shape=Qgis::MarkerShape::Circle, double size=DEFAULT_SIMPLEMARKER_SIZE, double angle=DEFAULT_SIMPLEMARKER_ANGLE, Qgis::ScaleMethod scaleMethod=DEFAULT_SCALE_METHOD)
Constructor for QgsFilledMarkerSymbolLayer.
Definition: qgsmarkersymbollayer.cpp:1725
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:71
QgsUnitTypes::RenderPercentage
@ RenderPercentage
Percentage of another measurement (e.g., canvas size, feature size)
Definition: qgsunittypes.h:172
QgsMarkerSymbolLayer::startRender
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
Definition: qgssymbollayer.cpp:528
QgsRenderContext
Contains information about the context of a rendering operation.
Definition: qgsrendercontext.h:59
DEFAULT_RASTERMARKER_SIZE
#define DEFAULT_RASTERMARKER_SIZE
Definition: qgsmarkersymbollayer.h:678
QgsSymbolLayerUtils::multiplyImageOpacity
static void multiplyImageOpacity(QImage *image, qreal opacity)
Multiplies opacity of image pixel values with a (global) transparency value.
Definition: qgssymbollayerutils.cpp:3988
QgsSymbolLayer::SELECTION_IS_OPAQUE
static const bool SELECTION_IS_OPAQUE
Whether styles for selected features ignore symbol alpha.
Definition: qgssymbollayer.h:661
QgsSimpleMarkerSymbolLayer::setColor
void setColor(const QColor &color) override
Sets the "representative" color for the symbol layer.
Definition: qgsmarkersymbollayer.cpp:1694
qgsunittypes.h
QgsSvgMarkerSymbolLayer::setParameters
void setParameters(const QMap< QString, QgsProperty > &parameters)
Sets the dynamic SVG parameters.
Definition: qgsmarkersymbollayer.cpp:2155
QgsSimpleMarkerSymbolLayer::setStrokeStyle
void setStrokeStyle(Qt::PenStyle strokeStyle)
Sets the marker's stroke style (e.g., solid, dashed, etc)
Definition: qgsmarkersymbollayer.h:273
QgsUnitTypes::RenderMillimeters
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:169
QgsRasterMarkerSymbolLayer::properties
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
Definition: qgsmarkersymbollayer.cpp:3113
DEFAULT_FONTMARKER_FONT
#define DEFAULT_FONTMARKER_FONT
Definition: qgsmarkersymbollayer.h:848
QgsMarkerSymbolLayer
Abstract base class for marker symbol layers.
Definition: qgssymbollayer.h:705
QgsSimpleMarkerSymbolLayer::ogrFeatureStyle
QString ogrFeatureStyle(double mmScaleFactor, double mapUnitScaleFactor) const override
Definition: qgsmarkersymbollayer.cpp:1301
qgsdxfpaintdevice.h
QgsRasterMarkerSymbolLayer::setOpacity
void setOpacity(double opacity)
Set the marker opacity.
Definition: qgsmarkersymbollayer.h:756
QgsRasterMarkerSymbolLayer::copyCommonProperties
void copyCommonProperties(QgsRasterMarkerSymbolLayer *other) const
Copies common properties to another layer.
Definition: qgsmarkersymbollayer.cpp:3140
QgsSymbolLayer::PropertyCapStyle
@ PropertyCapStyle
Line cap style.
Definition: qgssymbollayer.h:181
Qgis::MarkerShape::Star
@ Star
Star.
QgsFontMarkerSymbolLayer::setStrokeColor
void setStrokeColor(const QColor &color) override
Sets the stroke color for the symbol layer.
Definition: qgsmarkersymbollayer.h:958
QgsSymbolLayerUtils::encodePenStyle
static QString encodePenStyle(Qt::PenStyle style)
Definition: qgssymbollayerutils.cpp:153
QgsRenderContext::currentFrame
long long currentFrame() const
Returns the current frame number of the map (in frames per second), for maps which are part of an ani...
Definition: qgsrendercontext.cpp:695
QgsRasterMarkerSymbolLayer::mapUnitScale
QgsMapUnitScale mapUnitScale() const override
Definition: qgsmarkersymbollayer.cpp:3171
DEFAULT_SIMPLEMARKER_JOINSTYLE
#define DEFAULT_SIMPLEMARKER_JOINSTYLE
Definition: qgsmarkersymbollayer.h:26
QgsSymbol
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:92
QgsRasterMarkerSymbolLayer::bounds
QRectF bounds(QPointF point, QgsSymbolRenderContext &context) override
Returns the approximate bounding box of the marker symbol layer, taking into account any data defined...
Definition: qgsmarkersymbollayer.cpp:3176
QgsMarkerSymbolLayer::setMapUnitScale
void setMapUnitScale(const QgsMapUnitScale &scale) override
Definition: qgssymbollayer.cpp:706
QgsSimpleMarkerSymbolLayer::clone
QgsSimpleMarkerSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
Definition: qgsmarkersymbollayer.cpp:1252
qgsimageoperation.h
QgsSymbolLayerUtils::svgSymbolPathToName
static QString svgSymbolPathToName(const QString &path, const QgsPathResolver &pathResolver)
Determines an SVG symbol's name from its path.
Definition: qgssymbollayerutils.cpp:4303
QgsMarkerSymbolLayer::mSizeUnit
QgsUnitTypes::RenderUnit mSizeUnit
Marker size unit.
Definition: qgssymbollayer.h:995
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
qgsfontutils.h
QgsRenderContext::scaleFactor
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
Definition: qgsrendercontext.h:266
QgsSimpleMarkerSymbolLayer::properties
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
Definition: qgsmarkersymbollayer.cpp:1227
QgsSymbolLayer::PropertyStrokeColor
@ PropertyStrokeColor
Stroke color.
Definition: qgssymbollayer.h:148
QgsDxfExport::writeLine
void writeLine(const QgsPoint &pt1, const QgsPoint &pt2, const QString &layer, const QString &lineStyleName, const QColor &color, double width=-1)
Write line (as a polyline)
Definition: qgsdxfexport.cpp:1287
QgsSvgMarkerSymbolLayer::setMapUnitScale
void setMapUnitScale(const QgsMapUnitScale &scale) override
Definition: qgsmarkersymbollayer.cpp:2490
QgsAnimatedMarkerSymbolLayer
Animated marker symbol layer class.
Definition: qgsmarkersymbollayer.h:1091
QgsFilledMarkerSymbolLayer::startRender
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
Definition: qgsmarkersymbollayer.cpp:1781
QgsFilledMarkerSymbolLayer::color
QColor color() const override
Returns the "representative" color of the symbol layer.
Definition: qgsmarkersymbollayer.cpp:1882
QgsSymbolLayerUtils::decodeColor
static QColor decodeColor(const QString &str)
Definition: qgssymbollayerutils.cpp:69
QgsRasterMarkerSymbolLayer::clone
QgsRasterMarkerSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
Definition: qgsmarkersymbollayer.cpp:3132
QgsSvgMarkerSymbolLayer::createFromSld
static QgsSymbolLayer * createFromSld(QDomElement &element)
Definition: qgsmarkersymbollayer.cpp:2536
QgsMarkerSymbolLayer::mVerticalAnchorPoint
VerticalAnchorPoint mVerticalAnchorPoint
Vertical anchor point.
Definition: qgssymbollayer.h:1009
QgsDxfExport::mapUnitScaleFactor
static double mapUnitScaleFactor(double scale, QgsUnitTypes::RenderUnit symbolUnits, QgsUnitTypes::DistanceUnit mapUnits, double mapUnitsPerPixel=1.0)
Returns scale factor for conversion to map units.
Definition: qgsdxfexport.cpp:1823
Qgis::ScaleMethod::ScaleDiameter
@ ScaleDiameter
Calculate scale by the diameter.
QgsRenderContext::frameRate
double frameRate() const
Returns the frame rate of the map, for maps which are part of an animation.
Definition: qgsrendercontext.cpp:685
QgsFontMarkerSymbolLayer::setFontStyle
void setFontStyle(const QString &style)
Sets the font style for the font which will be used to render the point.
Definition: qgsmarkersymbollayer.h:941
QgsSymbolLayerUtils::wellKnownMarkerToSld
static void wellKnownMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &name, const QColor &color, const QColor &strokeColor, Qt::PenStyle strokeStyle, double strokeWidth=-1, double size=-1)
Definition: qgssymbollayerutils.cpp:2624
QgsFontMarkerSymbolLayer::clone
QgsFontMarkerSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
Definition: qgsmarkersymbollayer.cpp:3583
QgsSvgCache::containsParams
void containsParams(const QString &path, bool &hasFillParam, QColor &defaultFillColor, bool &hasStrokeParam, QColor &defaultStrokeColor, bool &hasStrokeWidthParam, double &defaultStrokeWidth, bool blocking=false) const
Tests if an SVG file contains parameters for fill, stroke color, stroke width.
Definition: qgssvgcache.cpp:228
QgsSimpleMarkerSymbolLayer::writeSldMarker
void writeSldMarker(QDomDocument &doc, QDomElement &element, const QVariantMap &props) const override
Writes the symbol layer definition as a SLD XML element.
Definition: qgsmarkersymbollayer.cpp:1272
QgsSimpleMarkerSymbolLayer::setStrokeWidthUnit
void setStrokeWidthUnit(QgsUnitTypes::RenderUnit u)
Sets the unit for the width of the marker's stroke.
Definition: qgsmarkersymbollayer.h:340
QgsFontMarkerSymbolLayer::setOutputUnit
void setOutputUnit(QgsUnitTypes::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
Definition: qgsmarkersymbollayer.cpp:3641
QgsSimpleMarkerSymbolLayer::mSelBrush
QBrush mSelBrush
QBrush to use as fill of selected symbols.
Definition: qgsmarkersymbollayer.h:407
QgsSvgMarkerSymbolLayer::mParameters
QMap< QString, QgsProperty > mParameters
Definition: qgsmarkersymbollayer.h:664
QgsSvgMarkerSymbolLayer::setStrokeWidthUnit
void setStrokeWidthUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the stroke width.
Definition: qgsmarkersymbollayer.h:618
Qgis::ScaleMethod
ScaleMethod
Scale methods.
Definition: qgis.h:219
QgsSymbolLayer::PropertyFontStyle
@ PropertyFontStyle
Font style.
Definition: qgssymbollayer.h:202
QgsMarkerSymbolLayer::mOffsetUnit
QgsUnitTypes::RenderUnit mOffsetUnit
Offset units.
Definition: qgssymbollayer.h:1001
QgsImageCache::totalFrameCount
int totalFrameCount(const QString &path, bool blocking=false)
Returns the total frame count of the image at the specified path.
Definition: qgsimagecache.cpp:244
QgsFilledMarkerSymbolLayer::stopRender
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
Definition: qgsmarkersymbollayer.cpp:1791
QgsSymbolRenderContext::selected
bool selected() const
Returns true if symbols should be rendered using the selected symbol coloring and style.
Definition: qgssymbolrendercontext.h:118
QgsSymbolLayerUtils::createDisplacementElement
static void createDisplacementElement(QDomDocument &doc, QDomElement &element, QPointF offset)
Definition: qgssymbollayerutils.cpp:2748
QgsSvgCache::svgViewboxSize
QSizeF svgViewboxSize(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 >())
Calculates the viewbox size of a (possibly cached) SVG file.
Definition: qgssvgcache.cpp:219
qt_defaultDpiY
Q_GUI_EXPORT int qt_defaultDpiY()
QgsMarkerSymbolLayer::mSize
double mSize
Marker size.
Definition: qgssymbollayer.h:993
QgsUnitTypes::decodeRenderUnit
static Q_INVOKABLE QgsUnitTypes::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
Definition: qgsunittypes.cpp:2948
QgsSimpleMarkerSymbolLayer::usesMapUnits
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
Definition: qgsmarkersymbollayer.cpp:1648
QgsSymbolRenderContext
Definition: qgssymbolrendercontext.h:35
QgsRasterMarkerSymbolLayer::setFixedAspectRatio
void setFixedAspectRatio(double ratio)
Set the marker aspect ratio between width and height to be used in rendering, if the value set is low...
Definition: qgsmarkersymbollayer.h:798
QgsSymbolLayerUtils::evaluatePropertiesMap
static QgsStringMap evaluatePropertiesMap(const QMap< QString, QgsProperty > &propertiesMap, const QgsExpressionContext &context)
Evaluates a map of properties using the given context and returns a variant map with evaluated expres...
Definition: qgssymbollayerutils.cpp:5078
QgsSimpleMarkerSymbolLayer::color
QColor color() const override
Returns the "representative" color of the symbol layer.
Definition: qgsmarkersymbollayer.cpp:1706
QgsFontMarkerSymbolLayer::stopRender
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
Definition: qgsmarkersymbollayer.cpp:3345
QgsMarkerSymbolLayer::HorizontalAnchorPoint
HorizontalAnchorPoint
Symbol horizontal anchor points.
Definition: qgssymbollayer.h:710
QgsSymbolLayerUtils::encodeScaleMethod
static QString encodeScaleMethod(Qgis::ScaleMethod scaleMethod)
Encodes a symbol scale method to a string.
Definition: qgssymbollayerutils.cpp:822
QgsSvgMarkerSymbolLayer::properties
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
Definition: qgsmarkersymbollayer.cpp:2418
QgsSvgMarkerSymbolLayer::strokeWidth
double strokeWidth() const
Definition: qgsmarkersymbollayer.h:598
QgsMarkerSymbolLayer::setOutputUnit
void setOutputUnit(QgsUnitTypes::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
Definition: qgssymbollayer.cpp:691
QgsSvgMarkerSymbolLayer::updateDefaultAspectRatio
double updateDefaultAspectRatio()
Calculates the default marker aspect ratio between width and height.
Definition: qgsmarkersymbollayer.cpp:2126
QgsSymbolLayerUtils::toPoint
static QPointF toPoint(const QVariant &value, bool *ok=nullptr)
Converts a value to a point.
Definition: qgssymbollayerutils.cpp:551
QgsFontMarkerSymbolLayer::setStrokeWidthUnit
void setStrokeWidthUnit(QgsUnitTypes::RenderUnit unit)
Sets the stroke width unit.
Definition: qgsmarkersymbollayer.h:1001
QgsSimpleMarkerSymbolLayer::bounds
QRectF bounds(QPointF point, QgsSymbolRenderContext &context) override
Returns the approximate bounding box of the marker symbol layer, taking into account any data defined...
Definition: qgsmarkersymbollayer.cpp:1655
QgsSimpleMarkerSymbolLayerBase::prepareMarkerShape
bool prepareMarkerShape(Qgis::MarkerShape shape)
Prepares the layer for drawing the specified shape (QPolygonF version)
Definition: qgsmarkersymbollayer.cpp:449
QgsSvgMarkerSymbolLayer::setStrokeColor
void setStrokeColor(const QColor &c) override
Sets the stroke color for the symbol layer.
Definition: qgsmarkersymbollayer.h:596
QgsMarkerSymbolLayer::markerOffset
void markerOffset(QgsSymbolRenderContext &context, double &offsetX, double &offsetY) const
Calculates the required marker offset, including both the symbol offset and any displacement required...
Definition: qgssymbollayer.cpp:558
QgsSimpleMarkerSymbolLayerBase
Abstract base class for simple marker symbol layers. Handles creation of the symbol shapes but leaves...
Definition: qgsmarkersymbollayer.h:46
Qgis::MarkerShape::ThirdArc
@ ThirdArc
A line-only one third arc (since QGIS 3.20)
QgsSimpleMarkerSymbolLayer::create
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsSimpleMarkerSymbolLayer.
Definition: qgsmarkersymbollayer.cpp:851
QgsSvgMarkerSymbolLayer::QgsSvgMarkerSymbolLayer
QgsSvgMarkerSymbolLayer(const QString &path, double size=DEFAULT_SVGMARKER_SIZE, double angle=DEFAULT_SVGMARKER_ANGLE, Qgis::ScaleMethod scaleMethod=DEFAULT_SCALE_METHOD)
Constructs SVG marker symbol layer with picture from given absolute path to a SVG file.
Definition: qgsmarkersymbollayer.cpp:1947
QgsSvgMarkerSymbolLayer::strokeColor
QColor strokeColor() const override
Returns the stroke color for the symbol layer.
Definition: qgsmarkersymbollayer.h:595
QgsSimpleMarkerSymbolLayer::mBrush
QBrush mBrush
QBrush corresponding to marker's fill style.
Definition: qgsmarkersymbollayer.h:400
QgsMarkerSymbolLayer::scaleMethod
Qgis::ScaleMethod scaleMethod() const
Returns the method to use for scaling the marker's size.
Definition: qgssymbollayer.h:832
DEFAULT_SVGMARKER_ANGLE
#define DEFAULT_SVGMARKER_ANGLE
Definition: qgsmarkersymbollayer.h:490
QgsSymbolLayer::PropertyOffset
@ PropertyOffset
Symbol offset.
Definition: qgssymbollayer.h:151
QgsSymbolLayer::PropertyCharacter
@ PropertyCharacter
Character, eg for font marker symbol layers.
Definition: qgssymbollayer.h:152
QgsProperty::propertyMapToVariantMap
static QVariantMap propertyMapToVariantMap(const QMap< QString, QgsProperty > &propertyMap)
Convert a map of QgsProperty to a map of QVariant This is useful to save a map of properties.
Definition: qgsproperty.cpp:208
QgsSymbolLayer
Definition: qgssymbollayer.h:54
QgsRenderContext::forceVectorOutput
bool forceVectorOutput() const
Returns true if rendering operations should use vector operations instead of any faster raster shortc...
Definition: qgsrendercontext.cpp:295
QgsSvgMarkerSymbolLayer::mHasFillParam
bool mHasFillParam
Definition: qgsmarkersymbollayer.h:661
QgsDxfExport::mapUnits
QgsUnitTypes::DistanceUnit mapUnits() const
Retrieve map units.
Definition: qgsdxfexport.cpp:262
QgsAnimatedMarkerSymbolLayer::QgsAnimatedMarkerSymbolLayer
QgsAnimatedMarkerSymbolLayer(const QString &path=QString(), double size=DEFAULT_RASTERMARKER_SIZE, double angle=DEFAULT_RASTERMARKER_ANGLE)
Constructor for animated marker symbol layer using the specified source image path.
Definition: qgsmarkersymbollayer.cpp:3769
QgsDxfPaintDevice
A paint device for drawing into dxf files.
Definition: qgsdxfpaintdevice.h:37
QgsSimpleMarkerSymbolLayer::fillColor
QColor fillColor() const override
Returns the fill color for the symbol layer.
Definition: qgsmarkersymbollayer.h:232
QgsRasterMarkerSymbolLayer::~QgsRasterMarkerSymbolLayer
~QgsRasterMarkerSymbolLayer() override
QgsRasterMarkerSymbolLayer::setMapUnitScale
void setMapUnitScale(const QgsMapUnitScale &scale) override
Definition: qgsmarkersymbollayer.cpp:3166
QgsSvgMarkerSymbolLayer::prepareExpressions
void prepareExpressions(const QgsSymbolRenderContext &context) override
Prepares all data defined property expressions for evaluation.
Definition: qgsmarkersymbollayer.cpp:3742
QgsUnitTypes::encodeUnit
static Q_INVOKABLE QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
Definition: qgsunittypes.cpp:122
QgsSvgMarkerSymbolLayer::outputUnit
QgsUnitTypes::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
Definition: qgsmarkersymbollayer.cpp:2480
QgsSimpleMarkerSymbolLayer::MAXIMUM_CACHE_WIDTH
static const int MAXIMUM_CACHE_WIDTH
Maximum width/height of cache image.
Definition: qgsmarkersymbollayer.h:418
QgsSvgMarkerSymbolLayer::startRender
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
Definition: qgsmarkersymbollayer.cpp:2166
QgsRasterMarkerSymbolLayer::preservedAspectRatio
bool preservedAspectRatio() const
Returns the preserved aspect ratio value, true if fixed aspect ratio has been lower or equal to 0.
Definition: qgsmarkersymbollayer.h:775
QgsRasterMarkerSymbolLayer::color
QColor color() const override
Returns the "representative" color of the symbol layer.
Definition: qgsmarkersymbollayer.cpp:3161
QgsSvgMarkerSymbolLayer::mStrokeWidthMapUnitScale
QgsMapUnitScale mStrokeWidthMapUnitScale
Definition: qgsmarkersymbollayer.h:667
QgsSymbolRenderContext::fields
QgsFields fields() const
Fields of the layer.
Definition: qgssymbolrendercontext.h:168
QgsRasterMarkerSymbolLayer::layerType
QString layerType() const override
Returns a string that represents this layer type.
Definition: qgsmarkersymbollayer.cpp:2899
QgsSvgCache::svgAsPicture
QPicture svgAsPicture(const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, bool forceVectorOutput=false, double fixedAspectRatio=0, bool blocking=false, const QMap< QString, QString > &parameters=QMap< QString, QString >())
Returns an SVG drawing as a QPicture.
Definition: qgssvgcache.cpp:185
QgsDxfPaintDevice::setLayer
void setLayer(const QString &layer)
Definition: qgsdxfpaintdevice.cpp:90
QgsSymbol::type
Qgis::SymbolType type() const
Returns the symbol's type.
Definition: qgssymbol.h:152
QgsSimpleMarkerSymbolLayer::setPenCapStyle
void setPenCapStyle(Qt::PenCapStyle style)
Sets the marker's stroke cap style (e.g., flat, round, etc).
Definition: qgsmarkersymbollayer.h:314
QgsSymbolLayerUtils::decodeScaleMethod
static Qgis::ScaleMethod decodeScaleMethod(const QString &str)
Decodes a symbol scale method from a string.
Definition: qgssymbollayerutils.cpp:838
QgsSvgMarkerSymbolLayer::fillColor
QColor fillColor() const override
Returns the fill color for the symbol layer.
Definition: qgsmarkersymbollayer.h:592
Qgis::MarkerShape::Diamond
@ Diamond
Diamond.
QgsSvgMarkerSymbolLayer::setStrokeWidth
void setStrokeWidth(double w)
Definition: qgsmarkersymbollayer.h:599
QgsFontMarkerSymbolLayer::createFromSld
static QgsSymbolLayer * createFromSld(QDomElement &element)
Creates a new QgsFontMarkerSymbolLayer from an SLD XML element.
Definition: qgsmarkersymbollayer.cpp:3685
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:2265
QgsSimpleMarkerSymbolLayerBase::decodeShape
static Qgis::MarkerShape decodeShape(const QString &name, bool *ok=nullptr)
Attempts to decode a string representation of a shape name to the corresponding shape.
Definition: qgsmarkersymbollayer.cpp:313
QgsRenderContext::setFlag
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
Definition: qgsrendercontext.cpp:216
QgsFontMarkerSymbolLayer::layerType
QString layerType() const override
Returns a string that represents this layer type.
Definition: qgsmarkersymbollayer.cpp:3285
QgsMapToPixel::mapRotation
double mapRotation() const
Returns the current map rotation in degrees (clockwise).
Definition: qgsmaptopixel.h:269
QgsSvgMarkerSymbolLayer::setPreservedAspectRatio
bool setPreservedAspectRatio(bool par)
Set preserved the marker aspect ratio between width and height.
Definition: qgsmarkersymbollayer.cpp:2141
QgsSvgMarkerSymbolLayer::path
QString path() const
Returns the marker SVG path.
Definition: qgsmarkersymbollayer.h:541
QgsFontUtils::translateNamedStyle
static QString translateNamedStyle(const QString &namedStyle)
Returns the localized named style of a font, if such a translation is available.
Definition: qgsfontutils.cpp:484
DEFAULT_FONTMARKER_SIZE
#define DEFAULT_FONTMARKER_SIZE
Definition: qgsmarkersymbollayer.h:850
QgsSimpleMarkerSymbolLayer::writeDxf
bool writeDxf(QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, QgsSymbolRenderContext &context, QPointF shift=QPointF(0.0, 0.0)) const override
write as DXF
Definition: qgsmarkersymbollayer.cpp:1426
QgsSimpleMarkerSymbolLayer
Simple marker symbol layer, consisting of a rendered shape with solid fill color and an stroke.
Definition: qgsmarkersymbollayer.h:176
QgsFontMarkerSymbolLayer::writeSldMarker
void writeSldMarker(QDomDocument &doc, QDomElement &element, const QVariantMap &props) const override
Writes the symbol layer definition as a SLD XML element.
Definition: qgsmarkersymbollayer.cpp:3604
QgsSimpleMarkerSymbolLayerBase::mPolygon
QPolygonF mPolygon
Polygon of points in shape. If polygon is empty then shape is using mPath.
Definition: qgsmarkersymbollayer.h:150
DEFAULT_FONTMARKER_CHR
#define DEFAULT_FONTMARKER_CHR
Definition: qgsmarkersymbollayer.h:849
QgsFilledMarkerSymbolLayer::subSymbol
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
Definition: qgsmarkersymbollayer.cpp:1830
QgsSvgMarkerSymbolLayer::mStrokeWidth
double mStrokeWidth
Definition: qgsmarkersymbollayer.h:663
QgsSvgMarkerSymbolLayer
Definition: qgsmarkersymbollayer.h:496
QgsSymbolLayer::PropertySize
@ PropertySize
Symbol size.
Definition: qgssymbollayer.h:144
QgsSimpleMarkerSymbolLayer::QgsSimpleMarkerSymbolLayer
QgsSimpleMarkerSymbolLayer(Qgis::MarkerShape shape=Qgis::MarkerShape::Circle, double size=DEFAULT_SIMPLEMARKER_SIZE, double angle=DEFAULT_SIMPLEMARKER_ANGLE, Qgis::ScaleMethod scaleMethod=DEFAULT_SCALE_METHOD, const QColor &color=DEFAULT_SIMPLEMARKER_COLOR, const QColor &strokeColor=DEFAULT_SIMPLEMARKER_BORDERCOLOR, Qt::PenJoinStyle penJoinStyle=DEFAULT_SIMPLEMARKER_JOINSTYLE)
Constructor for QgsSimpleMarkerSymbolLayer.
Definition: qgsmarkersymbollayer.cpp:841
QgsSymbolLayer::copyPaintEffect
void copyPaintEffect(QgsSymbolLayer *destLayer) const
Copies paint effect of this layer to another symbol layer.
Definition: qgssymbollayer.cpp:491
QgsSymbolLayerUtils::decodePoint
static QPointF decodePoint(const QString &string)
Decodes a QSizeF from a string.
Definition: qgssymbollayerutils.cpp:543
Qgis::SymbolRenderHint::DynamicRotation
@ DynamicRotation
Rotation of symbol may be changed during rendering and symbol should not be cached.
QgsSymbolLayer::PropertyStrokeStyle
@ PropertyStrokeStyle
Stroke style (eg solid, dashed)
Definition: qgssymbollayer.h:150
QgsMarkerSymbolLayer::outputUnit
QgsUnitTypes::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
Definition: qgssymbollayer.cpp:697
QgsSymbolLayerUtils::rescaleUom
static double rescaleUom(double size, QgsUnitTypes::RenderUnit unit, const QVariantMap &props)
Rescales the given size based on the uomScale found in the props, if any is found,...
Definition: qgssymbollayerutils.cpp:4742
QgsFilledMarkerSymbolLayer::layerType
QString layerType() const override
Returns a string that represents this layer type.
Definition: qgsmarkersymbollayer.cpp:1776
QgsApplication::imageCache
static QgsImageCache * imageCache()
Returns the application's image cache, used for caching resampled versions of raster images.
Definition: qgsapplication.cpp:2365
QgsRasterMarkerSymbolLayer::calculateAspectRatio
double calculateAspectRatio(QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedAspectRatio) const
Calculates the marker aspect ratio between width and height.
Definition: qgsmarkersymbollayer.cpp:3038
qgsrendercontext.h
QgsFontMarkerSymbolLayer::resolveFonts
static void resolveFonts(const QVariantMap &properties, const QgsReadWriteContext &context)
Resolves fonts from a properties map, raising warnings in the specified context if the required fonts...
Definition: qgsmarkersymbollayer.cpp:3733
QgsRasterMarkerSymbolLayer::setPath
void setPath(const QString &path)
Set the marker raster image path.
Definition: qgsmarkersymbollayer.cpp:2869
DEFAULT_SIMPLEMARKER_BORDERCOLOR
#define DEFAULT_SIMPLEMARKER_BORDERCOLOR
Definition: qgsmarkersymbollayer.h:25
DEFAULT_FONTMARKER_BORDERCOLOR
#define DEFAULT_FONTMARKER_BORDERCOLOR
Definition: qgsmarkersymbollayer.h:852
QgsSimpleMarkerSymbolLayer::prepareCache
bool prepareCache(QgsSymbolRenderContext &context)
Prepares cache image.
Definition: qgsmarkersymbollayer.cpp:1023
QgsSimpleMarkerSymbolLayer::strokeWidth
double strokeWidth() const
Returns the width of the marker's stroke.
Definition: qgsmarkersymbollayer.h:322
QgsSimpleMarkerSymbolLayer::startRender
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
Definition: qgsmarkersymbollayer.cpp:957
QgsDxfExport::writeCircle
void writeCircle(const QString &layer, const QColor &color, const QgsPoint &pt, double radius, const QString &lineStyleName, double width)
Write circle (as polyline)
Definition: qgsdxfexport.cpp:1460
QgsFontMarkerSymbolLayer::setPenJoinStyle
void setPenJoinStyle(Qt::PenJoinStyle style)
Sets the stroke join style.
Definition: qgsmarkersymbollayer.h:1041
QgsRasterMarkerSymbolLayer
Raster marker symbol layer class.
Definition: qgsmarkersymbollayer.h:687
QgsFontUtils::fontFamilyMatchOnSystem
static bool fontFamilyMatchOnSystem(const QString &family, QString *chosen=nullptr, bool *match=nullptr)
Check whether font family is on system.
Definition: qgsfontutils.cpp:100
QgsSimpleMarkerSymbolLayer::mStrokeColor
QColor mStrokeColor
Stroke color.
Definition: qgsmarkersymbollayer.h:384
QgsSvgMarkerSymbolLayer::renderPoint
void renderPoint(QPointF point, QgsSymbolRenderContext &context) override
Renders a marker at the specified point.
Definition: qgsmarkersymbollayer.cpp:2177
QgsSvgMarkerSymbolLayer::mStrokeWidthUnit
QgsUnitTypes::RenderUnit mStrokeWidthUnit
Definition: qgsmarkersymbollayer.h:666
QgsSymbolLayer::restoreOldDataDefinedProperties
void restoreOldDataDefinedProperties(const QVariantMap &stringMap)
Restores older data defined properties from string map.
Definition: qgssymbollayer.cpp:362
QgsSymbolLayer::PropertyName
@ PropertyName
Name, eg shape name for simple markers.
Definition: qgssymbollayer.h:146
QgsMarkerSymbolLayer::setOffset
void setOffset(QPointF offset)
Sets the marker's offset, which is the horizontal and vertical displacement which the rendered marker...
Definition: qgssymbollayer.h:842
QgsRasterMarkerSymbolLayer::mPath
QString mPath
Definition: qgsmarkersymbollayer.h:828
QgsSvgMarkerSymbolLayer::clone
QgsSvgMarkerSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
Definition: qgsmarkersymbollayer.cpp:2451
QgsMapUnitScale
Struct for storing maximum and minimum scales for measurements in map units.
Definition: qgsmapunitscale.h:36
Qgis::MarkerShape::SquareWithCorners
@ SquareWithCorners
A square with diagonal corners (since QGIS 3.18)
QgsScopedQPainterState
Scoped object for saving and restoring a QPainter object's state.
Definition: qgsrendercontext.h:1336
QgsSimpleMarkerSymbolLayer::setStrokeWidth
void setStrokeWidth(double w)
Sets the width of the marker's stroke.
Definition: qgsmarkersymbollayer.h:331
QgsSymbolLayer::mDataDefinedProperties
QgsPropertyCollection mDataDefinedProperties
Definition: qgssymbollayer.h:651
QgsSymbolLayer::PropertyStrokeWidth
@ PropertyStrokeWidth
Stroke width.
Definition: qgssymbollayer.h:149
QgsSimpleMarkerSymbolLayerBase::bounds
QRectF bounds(QPointF point, QgsSymbolRenderContext &context) override
Returns the approximate bounding box of the marker symbol layer, taking into account any data defined...
Definition: qgsmarkersymbollayer.cpp:287
QgsFillSymbol::createSimple
static QgsFillSymbol * createSimple(const QVariantMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties.
Definition: qgsfillsymbol.cpp:20
QgsRingSequence
QVector< QgsPointSequence > QgsRingSequence
Definition: qgsabstractgeometry.h:56
QgsRasterMarkerSymbolLayer::path
QString path() const
Returns the marker raster image path.
Definition: qgsmarkersymbollayer.h:735
QgsMarkerSymbolLayer::setOffsetUnit
void setOffsetUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the symbol's offset.
Definition: qgssymbollayer.h:860
QgsRasterMarkerSymbolLayer::resolvePaths
static void resolvePaths(QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving)
Turns relative paths in properties map to absolute when reading and vice versa when writing.
Definition: qgsmarkersymbollayer.cpp:2857
QgsSimpleMarkerSymbolLayer::mStrokeStyle
Qt::PenStyle mStrokeStyle
Stroke style.
Definition: qgsmarkersymbollayer.h:386
QgsSymbolLayerUtils::encodePoint
static QString encodePoint(QPointF point)
Encodes a QPointF to a string.
Definition: qgssymbollayerutils.cpp:538
Qgis::MarkerShape::QuarterCircle
@ QuarterCircle
Quarter circle (top left quarter)
QgsApplication::svgCache
static QgsSvgCache * svgCache()
Returns the application's SVG cache, used for caching SVG images and handling parameter replacement w...
Definition: qgsapplication.cpp:2360
QgsAbstractPropertyCollection::valueAsString
QString valueAsString(int key, const QgsExpressionContext &context, const QString &defaultString=QString(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a string.
Definition: qgspropertycollection.cpp:42
QgsSymbolLayer::usedAttributes
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns the set of attributes referenced by the layer.
Definition: qgssymbollayer.cpp:328
Qgis::MarkerShape::HalfSquare
@ HalfSquare
Half square (left half)
DEG2RAD
#define DEG2RAD(x)
Definition: qgsdistancearea.cpp:40
QgsSvgMarkerSymbolLayer::setStrokeWidthMapUnitScale
void setStrokeWidthMapUnitScale(const QgsMapUnitScale &scale)
Definition: qgsmarkersymbollayer.h:626
QgsSimpleMarkerSymbolLayer::strokeColor
QColor strokeColor() const override
Returns the marker's stroke color.
Definition: qgsmarkersymbollayer.h:245
QgsSymbolLayerUtils::decodeSldUom
static QgsUnitTypes::RenderUnit decodeSldUom(const QString &str, double *scaleFactor=nullptr)
Decodes a SLD unit of measure string to a render unit.
Definition: qgssymbollayerutils.cpp:740
QgsSvgMarkerSymbolLayer::writeSldMarker
void writeSldMarker(QDomDocument &doc, QDomElement &element, const QVariantMap &props) const override
Writes the symbol layer definition as a SLD XML element.
Definition: qgsmarkersymbollayer.cpp:2505
QgsSimpleMarkerSymbolLayerBase::shape
Qgis::MarkerShape shape() const
Returns the shape for the rendered marker symbol.
Definition: qgsmarkersymbollayer.h:79
QgsRenderContext::convertToPainterUnits
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
Definition: qgsrendercontext.cpp:367
Qgis::MarkerShape::Line
@ Line
Vertical line.
QgsSymbolLayerUtils::decodePenCapStyle
static Qt::PenCapStyle decodePenCapStyle(const QString &str)
Definition: qgssymbollayerutils.cpp:250
Qgis::MarkerShape::LeftHalfTriangle
@ LeftHalfTriangle
Left half of triangle.
QgsSimpleMarkerSymbolLayer::mSelPen
QPen mSelPen
QPen to use as stroke of selected symbols.
Definition: qgsmarkersymbollayer.h:405
QgsAnimatedMarkerSymbolLayer::fetchImage
QImage fetchImage(QgsRenderContext &context, const QString &path, QSize size, bool preserveAspectRatio, double opacity) const override
Fetches the image to render.
Definition: qgsmarkersymbollayer.cpp:3833
QgsSimpleMarkerSymbolLayer::mapUnitScale
QgsMapUnitScale mapUnitScale() const override
Definition: qgsmarkersymbollayer.cpp:1639
QgsMarkerSymbolLayer::mScaleMethod
Qgis::ScaleMethod mScaleMethod
Marker size scaling method.
Definition: qgssymbollayer.h:1005
QgsRenderContext::selectionColor
QColor selectionColor() const
Returns the color to use when rendering selected features.
Definition: qgsrendercontext.h:382
QgsSimpleMarkerSymbolLayer::createFromSld
static QgsSymbolLayer * createFromSld(QDomElement &element)
Creates a new QgsSimpleMarkerSymbolLayer from an SLD XML element.
Definition: qgsmarkersymbollayer.cpp:1363
QgsSvgMarkerSymbolLayer::calculateAspectRatio
double calculateAspectRatio(QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedAspectRatio) const
Calculates the marker aspect ratio between width and height.
Definition: qgsmarkersymbollayer.cpp:2338
QgsMarkerSymbolLayer::setOffsetMapUnitScale
void setOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the symbol's offset.
Definition: qgssymbollayer.h:877
QgsFilledMarkerSymbolLayer::setOutputUnit
void setOutputUnit(QgsUnitTypes::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
Definition: qgsmarkersymbollayer.cpp:1894
Qgis::RenderContextFlag::RenderBlocking
@ RenderBlocking
Render and load remote sources in the same thread to ensure rendering remote sources (svg and images)...
QgsStringMap
QMap< QString, QString > QgsStringMap
Definition: qgis.h:2781
QgsSimpleMarkerSymbolLayer::setMapUnitScale
void setMapUnitScale(const QgsMapUnitScale &scale) override
Definition: qgsmarkersymbollayer.cpp:1633
QgsMarkerSymbolLayer::mOffset
QPointF mOffset
Marker offset.
Definition: qgssymbollayer.h:999
QgsFontMarkerSymbolLayer::create
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsFontMarkerSymbolLayer from a property map (see properties())
Definition: qgsmarkersymbollayer.cpp:3232
QgsWkbTypes::PointGeometry
@ PointGeometry
Definition: qgswkbtypes.h:142
QgsFontMarkerSymbolLayer::fontStyle
QString fontStyle() const
Returns the font style for the associated font which will be used to render the point.
Definition: qgsmarkersymbollayer.h:933
QgsSimpleMarkerSymbolLayerBase::renderPoint
void renderPoint(QPointF point, QgsSymbolRenderContext &context) override
Renders a marker at the specified point.
Definition: qgsmarkersymbollayer.cpp:201
QgsFilledMarkerSymbolLayer::setSubSymbol
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
Definition: qgsmarkersymbollayer.cpp:1835
QgsAnimatedMarkerSymbolLayer::layerType
QString layerType() const override
Returns a string that represents this layer type.
Definition: qgsmarkersymbollayer.cpp:3797
QgsMarkerSymbolLayer::mHorizontalAnchorPoint
HorizontalAnchorPoint mHorizontalAnchorPoint
Horizontal anchor point.
Definition: qgssymbollayer.h:1007
QgsSvgMarkerSymbolLayer::stopRender
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
Definition: qgsmarkersymbollayer.cpp:2172
QgsSvgMarkerSymbolLayer::setFillColor
void setFillColor(const QColor &color) override
Sets the fill color for the symbol layer.
Definition: qgsmarkersymbollayer.h:593
QgsAnimatedMarkerSymbolLayer::~QgsAnimatedMarkerSymbolLayer
~QgsAnimatedMarkerSymbolLayer() override
QgsSvgMarkerSymbolLayer::setFixedAspectRatio
void setFixedAspectRatio(double ratio)
Set the marker aspect ratio between width and height to be used in rendering, if the value set is low...
Definition: qgsmarkersymbollayer.h:590
QgsSvgMarkerSymbolLayer::resolvePaths
static void resolvePaths(QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving)
Turns relative paths in properties map to absolute when reading and vice versa when writing.
Definition: qgsmarkersymbollayer.cpp:2062
QgsFilledMarkerSymbolLayer::clone
QgsFilledMarkerSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
Definition: qgsmarkersymbollayer.cpp:1821
QgsSimpleMarkerSymbolLayerBase::prepareMarkerPath
bool prepareMarkerPath(Qgis::MarkerShape symbol)
Prepares the layer for drawing the specified shape (QPainterPath version)
Definition: qgsmarkersymbollayer.cpp:671
QgsPointSequence
QVector< QgsPoint > QgsPointSequence
Definition: qgsabstractgeometry.h:52
QgsPropertyCollection::value
QVariant value(int key, const QgsExpressionContext &context, const QVariant &defaultValue=QVariant()) const override
Returns the calculated value of the property with the specified key from within the collection.
Definition: qgspropertycollection.cpp:228
c
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
Definition: porting_processing.dox:1
QgsSimpleMarkerSymbolLayerBase::mPath
QPainterPath mPath
Painter path representing shape. If mPolygon is empty then the shape is stored in mPath.
Definition: qgsmarkersymbollayer.h:153
Qgis::MarkerShape::Pentagon
@ Pentagon
Pentagon.
QgsMapToPixel
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:38
QgsDxfExport::writeFilledCircle
void writeFilledCircle(const QString &layer, const QColor &color, const QgsPoint &pt, double radius)
Write filled circle (as hatch)
Definition: qgsdxfexport.cpp:1423
QgsFilledMarkerSymbolLayer::hasDataDefinedProperties
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
Definition: qgsmarkersymbollayer.cpp:1866
DEFAULT_SVGMARKER_SIZE
#define DEFAULT_SVGMARKER_SIZE
Definition: qgsmarkersymbollayer.h:489
QgsSimpleMarkerSymbolLayer::setStrokeColor
void setStrokeColor(const QColor &color) override
Sets the marker's stroke color.
Definition: qgsmarkersymbollayer.h:254
QgsFeature::hasGeometry
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:230
qgsimagecache.h
QgsAnimatedMarkerSymbolLayer::properties
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
Definition: qgsmarkersymbollayer.cpp:3802
QgsSimpleMarkerSymbolLayer::mStrokeWidthUnit
QgsUnitTypes::RenderUnit mStrokeWidthUnit
Stroke width units.
Definition: qgsmarkersymbollayer.h:390
QgsSimpleMarkerSymbolLayer::layerType
QString layerType() const override
Returns a string that represents this layer type.
Definition: qgsmarkersymbollayer.cpp:952
QgsSymbolLayerUtils::svgSymbolNameToPath
static QString svgSymbolNameToPath(const QString &name, const QgsPathResolver &pathResolver)
Determines an SVG symbol's path from its name.
Definition: qgssymbollayerutils.cpp:4237
QgsMarkerSymbolLayer::mLineAngle
double mLineAngle
Line rotation angle (see setLineAngle() for details)
Definition: qgssymbollayer.h:991
QgsSvgMarkerSymbolLayer::~QgsSvgMarkerSymbolLayer
~QgsSvgMarkerSymbolLayer() override
QgsFontMarkerSymbolLayer
Definition: qgsmarkersymbollayer.h:860
DEFAULT_SCALE_METHOD
#define DEFAULT_SCALE_METHOD
Definition: qgssymbollayer.h:19
Qgis::MarkerShape::Circle
@ Circle
Circle.
QgsFontMarkerSymbolLayer::renderPoint
void renderPoint(QPointF point, QgsSymbolRenderContext &context) override
Renders a marker at the specified point.
Definition: qgsmarkersymbollayer.cpp:3441
QgsSymbolLayerUtils::rotationFromSldElement
static bool rotationFromSldElement(QDomElement &element, QString &rotationFunc)
Definition: qgssymbollayerutils.cpp:2717
QgsFilledMarkerSymbolLayer::usesMapUnits
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
Definition: qgsmarkersymbollayer.cpp:1887
QgsSimpleMarkerSymbolLayerBase::encodeShape
static QString encodeShape(Qgis::MarkerShape shape)
Encodes a shape to its string representation.
Definition: qgsmarkersymbollayer.cpp:383
QgsSymbolLayer::PropertyAngle
@ PropertyAngle
Symbol angle.
Definition: qgssymbollayer.h:145
QgsFillSymbol
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
Definition: qgsfillsymbol.h:29
Qgis::ScaleMethod::ScaleArea
@ ScaleArea
Calculate scale by the area.
QgsUnitTypes::RenderMetersInMapUnits
@ RenderMetersInMapUnits
Meters value as Map units.
Definition: qgsunittypes.h:176
QgsSvgMarkerSymbolLayer::preservedAspectRatio
bool preservedAspectRatio() const
Returns the preserved aspect ratio value, true if fixed aspect ratio has been lower or equal to 0.
Definition: qgsmarkersymbollayer.h:567
QgsRenderContext::pathResolver
const QgsPathResolver & pathResolver() const
Returns the path resolver for conversion between relative and absolute paths during rendering operati...
Definition: qgsrendercontext.h:213
QgsUnitTypes::RenderUnknownUnit
@ RenderUnknownUnit
Mixed or unknown units.
Definition: qgsunittypes.h:175
QgsFilledMarkerSymbolLayer::properties
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
Definition: qgsmarkersymbollayer.cpp:1799
Qgis::MarkerShape::HalfArc
@ HalfArc
A line-only half arc (since QGIS 3.20)
QgsRasterMarkerSymbolLayer::mOpacity
double mOpacity
The marker default opacity.
Definition: qgsmarkersymbollayer.h:830
QgsSvgMarkerSymbolLayer::parameters
QMap< QString, QgsProperty > parameters() const
Returns the dynamic SVG parameters.
Definition: qgsmarkersymbollayer.h:605
QgsSymbolLayerUtils::decodePenJoinStyle
static Qt::PenJoinStyle decodePenJoinStyle(const QString &str)
Definition: qgssymbollayerutils.cpp:200
Qgis::MarkerShape::EquilateralTriangle
@ EquilateralTriangle
Equilateral triangle.
QgsSimpleMarkerSymbolLayer::mUsingCache
bool mUsingCache
true if using cached images of markers for drawing.
Definition: qgsmarkersymbollayer.h:415
QgsSvgMarkerSymbolLayer::usesMapUnits
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
Definition: qgsmarkersymbollayer.cpp:2444
Qgis::MarkerShape::QuarterSquare
@ QuarterSquare
Quarter square (top left quarter)
QgsAnimatedMarkerSymbolLayer::startRender
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
Definition: qgsmarkersymbollayer.cpp:3817
QgsSymbolLayerUtils::createRotationElement
static void createRotationElement(QDomDocument &doc, QDomElement &element, const QString &rotationFunc)
Definition: qgssymbollayerutils.cpp:2707
QgsRasterMarkerSymbolLayer::setCommonProperties
void setCommonProperties(const QVariantMap &properties)
Sets common class properties from a properties map.
Definition: qgsmarkersymbollayer.cpp:2823
QgsMarkerSymbolLayer::_rotatedOffset
static QPointF _rotatedOffset(QPointF offset, double angle)
Adjusts a marker offset to account for rotation.
Definition: qgssymbollayer.cpp:652
QgsMarkerSymbolLayer::offset
QPointF offset() const
Returns the marker's offset, which is the horizontal and vertical displacement which the rendered mar...
Definition: qgssymbollayer.h:851
QgsDxfPaintDevice::setOutputSize
void setOutputSize(const QRectF &r)
Definition: qgsdxfpaintdevice.h:46
QgsMarkerSymbolLayer::setSizeMapUnitScale
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the symbol's size.
Definition: qgssymbollayer.h:811
QgsMarkerSymbolLayer::setVerticalAnchorPoint
void setVerticalAnchorPoint(VerticalAnchorPoint v)
Sets the vertical anchor point for positioning the symbol.
Definition: qgssymbollayer.h:911
qgsdxfexport.h
QgsSimpleMarkerSymbolLayer::mCache
QImage mCache
Cached image of marker, if using cached version.
Definition: qgsmarkersymbollayer.h:403
QgsSimpleMarkerSymbolLayerBase::~QgsSimpleMarkerSymbolLayerBase
~QgsSimpleMarkerSymbolLayerBase() override
QgsSimpleMarkerSymbolLayerBase::calculateOffsetAndRotation
void calculateOffsetAndRotation(QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedRotation, QPointF &offset, double &angle) const
Calculates the marker offset and rotation.
Definition: qgsmarkersymbollayer.cpp:788
DEFAULT_FONTMARKER_JOINSTYLE
#define DEFAULT_FONTMARKER_JOINSTYLE
Definition: qgsmarkersymbollayer.h:853
QgsMarkerSymbolLayer::mAngle
double mAngle
Marker rotation angle, in degrees clockwise from north.
Definition: qgssymbollayer.h:989
QgsSimpleMarkerSymbolLayer::mPenCapStyle
Qt::PenCapStyle mPenCapStyle
Stroke pen cap style.
Definition: qgsmarkersymbollayer.h:396
QgsSymbolLayer::color
virtual QColor color() const
Returns the "representative" color of the symbol layer.
Definition: qgssymbollayer.cpp:247
QgsSimpleMarkerSymbolLayer::~QgsSimpleMarkerSymbolLayer
~QgsSimpleMarkerSymbolLayer() override
QgsSymbolLayerUtils::encodePenJoinStyle
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
Definition: qgssymbollayerutils.cpp:185
QgsImageCache::prepareAnimation
void prepareAnimation(const QString &path)
Prepares for optimized retrieval of frames for the animation at the given path.
Definition: qgsimagecache.cpp:288
QgsSymbolRenderContext::renderHints
Qgis::SymbolRenderHints renderHints() const
Returns the rendering hint flags for the symbol.
Definition: qgssymbolrendercontext.h:130
QgsFeature
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:55
QgsSymbolLayer::PropertyOpacity
@ PropertyOpacity
Opacity.
Definition: qgssymbollayer.h:179
QgsSvgMarkerSymbolLayer::mPath
QString mPath
Definition: qgsmarkersymbollayer.h:653
QgsSymbolRenderContext::renderContext
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
Definition: qgssymbolrendercontext.h:62
QgsDxfExport::symbologyScale
double symbologyScale() const
Returns the reference scale for output.
Definition: qgsdxfexport.h:229
QgsRasterMarkerSymbolLayer::create
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a raster marker symbol layer from a string map of properties.
Definition: qgsmarkersymbollayer.cpp:2802
QgsSymbolLayerUtils::estimateMaxSymbolBleed
static double estimateMaxSymbolBleed(QgsSymbol *symbol, const QgsRenderContext &context)
Returns the maximum estimated bleed for the symbol.
Definition: qgssymbollayerutils.cpp:934
QgsFontMarkerSymbolLayer::setStrokeWidthMapUnitScale
void setStrokeWidthMapUnitScale(const QgsMapUnitScale &scale)
Sets the stroke width map unit scale.
Definition: qgsmarkersymbollayer.h:1023
QgsDxfPaintDevice::setShift
void setShift(QPointF shift)
Definition: qgsdxfpaintdevice.cpp:98
Qgis::MarkerShape::RightHalfTriangle
@ RightHalfTriangle
Right half of triangle.
Qgis::MarkerShape::Octagon
@ Octagon
Octagon (since QGIS 3.18)
QgsDxfExport::clipValueToMapUnitScale
void clipValueToMapUnitScale(double &value, const QgsMapUnitScale &scale, double pixelToMMFactor) const
Clips value to scale minimum/maximum.
Definition: qgsdxfexport.cpp:1840
QgsSymbolLayer::PropertyHeight
@ PropertyHeight
Symbol height.
Definition: qgssymbollayer.h:154
QgsSymbolLayerUtils::parametricSvgToSld
static void parametricSvgToSld(QDomDocument &doc, QDomElement &graphicElem, const QString &path, const QColor &fillColor, double size, const QColor &strokeColor, double strokeWidth)
Encodes a reference to a parametric SVG into SLD, as a succession of parametric SVG using URL paramet...
Definition: qgssymbollayerutils.cpp:2462
Qgis::MarkerShape
MarkerShape
Marker shapes.
Definition: qgis.h:1370
qgslogger.h
Qgis::RenderContextFlag::RenderingSubSymbol
@ RenderingSubSymbol
Set whenever a sub-symbol of a parent symbol is currently being rendered. Can be used during symbol a...
QgsRenderContext::painter
QPainter * painter()
Returns the destination QPainter for the render operation.
Definition: qgsrendercontext.h:112
QgsSimpleMarkerSymbolLayer::outputUnit
QgsUnitTypes::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
Definition: qgsmarkersymbollayer.cpp:1624
QgsSimpleMarkerSymbolLayerBase::QgsSimpleMarkerSymbolLayerBase
QgsSimpleMarkerSymbolLayerBase(Qgis::MarkerShape shape=Qgis::MarkerShape::Circle, double size=DEFAULT_SIMPLEMARKER_SIZE, double angle=DEFAULT_SIMPLEMARKER_ANGLE, Qgis::ScaleMethod scaleMethod=DEFAULT_SCALE_METHOD)
Constructor for QgsSimpleMarkerSymbolLayerBase.
Definition: qgsmarkersymbollayer.cpp:100
DEFAULT_FONTMARKER_COLOR
#define DEFAULT_FONTMARKER_COLOR
Definition: qgsmarkersymbollayer.h:851
QgsSymbolLayerUtils::decodePenStyle
static Qt::PenStyle decodePenStyle(const QString &str)
Definition: qgssymbollayerutils.cpp:174
DEFAULT_SIMPLEMARKER_COLOR
#define DEFAULT_SIMPLEMARKER_COLOR
Definition: qgsmarkersymbollayer.h:24
QgsSvgMarkerSymbolLayer::writeDxf
bool writeDxf(QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, QgsSymbolRenderContext &context, QPointF shift=QPointF(0.0, 0.0)) const override
write as DXF
Definition: qgsmarkersymbollayer.cpp:2582
QgsImageOperation::overlayColor
static void overlayColor(QImage &image, const QColor &color)
Overlays a color onto an image.
Definition: qgsimageoperation.cpp:371
QgsRasterMarkerSymbolLayer::fetchImage
virtual QImage fetchImage(QgsRenderContext &context, const QString &path, QSize size, bool preserveAspectRatio, double opacity) const
Fetches the image to render.
Definition: qgsmarkersymbollayer.cpp:2996
QgsRasterMarkerSymbolLayer::mDefaultAspectRatio
double mDefaultAspectRatio
The marker default aspect ratio.
Definition: qgsmarkersymbollayer.h:832
QgsSymbolLayerUtils::displacementFromSldElement
static bool displacementFromSldElement(QDomElement &element, QPointF &offset)
Definition: qgssymbollayerutils.cpp:2783
QgsPropertyCollection::isActive
bool isActive(int key) const override
Returns true if the collection contains an active property with the specified key.
Definition: qgspropertycollection.cpp:268
QgsSymbolLayerUtils::externalMarkerToSld
static void externalMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &path, const QString &format, int *markIndex=nullptr, const QColor &color=QColor(), double size=-1)
Definition: qgssymbollayerutils.cpp:2550
QgsGeometry::type
QgsWkbTypes::GeometryType type
Definition: qgsgeometry.h:128
QgsReadWriteContext::pushMessage
void pushMessage(const QString &message, Qgis::MessageLevel level=Qgis::MessageLevel::Warning) const
Append a message to the context.
Definition: qgsreadwritecontext.cpp:57
QgsMarkerSymbolLayer::mOffsetMapUnitScale
QgsMapUnitScale mOffsetMapUnitScale
Offset map unit scale.
Definition: qgssymbollayer.h:1003
MathUtils::angle
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
QgsSymbolLayer::copyDataDefinedProperties
void copyDataDefinedProperties(QgsSymbolLayer *destLayer) const
Copies all data defined properties of this layer to another symbol layer.
Definition: qgssymbollayer.cpp:483
qgsfillsymbol.h
QgsSimpleMarkerSymbolLayerBase::shapeIsFilled
static bool shapeIsFilled(Qgis::MarkerShape shape)
Returns true if a symbol shape has a fill.
Definition: qgsmarkersymbollayer.cpp:113
QgsFontMarkerSymbolLayer::startRender
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
Definition: qgsmarkersymbollayer.cpp:3290
qgssymbol.h
QgsFontMarkerSymbolLayer::~QgsFontMarkerSymbolLayer
~QgsFontMarkerSymbolLayer() override
QgsPathResolver
Resolves relative paths into absolute paths and vice versa. Used for writing.
Definition: qgspathresolver.h:31
QgsRasterMarkerSymbolLayer::QgsRasterMarkerSymbolLayer
QgsRasterMarkerSymbolLayer(const QString &path=QString(), double size=DEFAULT_SVGMARKER_SIZE, double angle=DEFAULT_SVGMARKER_ANGLE, Qgis::ScaleMethod scaleMethod=DEFAULT_SCALE_METHOD)
Constructs raster marker symbol layer with picture from given absolute path to a raster image file.
Definition: qgsmarkersymbollayer.cpp:2790
QgsUnitTypes::RenderMapUnits
@ RenderMapUnits
Map units.
Definition: qgsunittypes.h:170
QgsSymbolLayerUtils::decodeMapUnitScale
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
Definition: qgssymbollayerutils.cpp:676
QgsSvgCache::svgAsImage
QImage svgAsImage(const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, bool &fitsInCache, double fixedAspectRatio=0, bool blocking=false, const QMap< QString, QString > &parameters=QMap< QString, QString >())
Returns an SVG drawing as a QImage.
Definition: qgssvgcache.cpp:125
Qgis::MarkerShape::ThirdCircle
@ ThirdCircle
One third circle (top left third)
QgsMarkerSymbolLayer::angle
double angle() const
Returns the rotation angle for the marker, in degrees clockwise from north.
Definition: qgssymbollayer.h:757
QgsSvgMarkerSymbolLayer::create
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates the symbol.
Definition: qgsmarkersymbollayer.cpp:1962
QgsFontMarkerSymbolLayer::fontFamily
QString fontFamily() const
Returns the font family name for the associated font which will be used to render the point.
Definition: qgsmarkersymbollayer.h:918
QgsSvgMarkerSymbolLayer::mFixedAspectRatio
double mFixedAspectRatio
The marker fixed aspect ratio.
Definition: qgsmarkersymbollayer.h:658
QgsSimpleMarkerSymbolLayerBase::calculateSize
double calculateSize(QgsSymbolRenderContext &context, bool &hasDataDefinedSize) const
Calculates the desired size of the marker, considering data defined size overrides.
Definition: qgsmarkersymbollayer.cpp:760
QgsRasterMarkerSymbolLayer::setPreservedAspectRatio
bool setPreservedAspectRatio(bool par)
Set preserved the marker aspect ratio between width and height.
Definition: qgsmarkersymbollayer.cpp:2875
QgsSimpleMarkerSymbolLayer::mPen
QPen mPen
QPen corresponding to marker's stroke style.
Definition: qgsmarkersymbollayer.h:398
QgsFontUtils::updateFontViaStyle
static bool updateFontViaStyle(QFont &f, const QString &fontstyle, bool fallback=false)
Updates font with named style and retain all font properties.
Definition: qgsfontutils.cpp:153
QgsSimpleMarkerSymbolLayer::setFillColor
void setFillColor(const QColor &color) override
Sets the fill color for the symbol layer.
Definition: qgsmarkersymbollayer.h:233
QgsAbstractPropertyCollection::valueAsColor
QColor valueAsColor(int key, const QgsExpressionContext &context, const QColor &defaultColor=QColor(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a color.
Definition: qgspropertycollection.cpp:54
QgsFontMarkerSymbolLayer::strokeWidth
double strokeWidth() const
Returns the marker's stroke width.
Definition: qgsmarkersymbollayer.h:969
QgsSvgMarkerSymbolLayer::mStrokeColor
QColor mStrokeColor
Definition: qgsmarkersymbollayer.h:662
Qgis::MarkerShape::Cross
@ Cross
Cross (lines only)
QgsDxfExport::writePolyline
void writePolyline(const QgsPointSequence &line, const QString &layer, const QString &lineStyleName, const QColor &color, double width=-1)
Draw dxf primitives (LWPOLYLINE)
Definition: qgsdxfexport.cpp:957
QgsSymbolLayer::PropertyJoinStyle
@ PropertyJoinStyle
Line join style.
Definition: qgssymbollayer.h:157
QgsSimpleMarkerSymbolLayer::drawMarker
void drawMarker(QPainter *p, QgsSymbolRenderContext &context)
Draws the marker shape in the specified painter.
Definition: qgsmarkersymbollayer.cpp:1412
QgsFontMarkerSymbolLayer::bounds
QRectF bounds(QPointF point, QgsSymbolRenderContext &context) override
Returns the approximate bounding box of the marker symbol layer, taking into account any data defined...
Definition: qgsmarkersymbollayer.cpp:3647
QgsSimpleMarkerSymbolLayerBase::stopRender
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
Definition: qgsmarkersymbollayer.cpp:196
QgsSymbolLayer::PropertyWidth
@ PropertyWidth
Symbol width.
Definition: qgssymbollayer.h:153
QgsFilledMarkerSymbolLayer::~QgsFilledMarkerSymbolLayer
~QgsFilledMarkerSymbolLayer() override
Qgis::MarkerShape::Triangle
@ Triangle
Triangle.
DEFAULT_RASTERMARKER_ANGLE
#define DEFAULT_RASTERMARKER_ANGLE
Definition: qgsmarkersymbollayer.h:679
QgsSimpleMarkerSymbolLayer::mStrokeWidthMapUnitScale
QgsMapUnitScale mStrokeWidthMapUnitScale
Stroke width map unit scale.
Definition: qgsmarkersymbollayer.h:392
DEFAULT_SIMPLEMARKER_SIZE
#define DEFAULT_SIMPLEMARKER_SIZE
Definition: qgsmarkersymbollayer.h:27
QgsSimpleMarkerSymbolLayer::mStrokeWidth
double mStrokeWidth
Stroke width.
Definition: qgsmarkersymbollayer.h:388