QGIS API Documentation  3.14.0-Pi (9f7028fd23)
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 
30 #include <QPainter>
31 #include <QSvgRenderer>
32 #include <QFileInfo>
33 #include <QDir>
34 #include <QDomDocument>
35 #include <QDomElement>
36 
37 #include <cmath>
38 
39 Q_GUI_EXPORT extern int qt_defaultDpiX();
40 Q_GUI_EXPORT extern int qt_defaultDpiY();
41 
42 static void _fixQPictureDPI( QPainter *p )
43 {
44  // QPicture makes an assumption that we drawing to it with system DPI.
45  // Then when being drawn, it scales the painter. The following call
46  // negates the effect. There is no way of setting QPicture's DPI.
47  // See QTBUG-20361
48  p->scale( static_cast< double >( qt_defaultDpiX() ) / p->device()->logicalDpiX(),
49  static_cast< double >( qt_defaultDpiY() ) / p->device()->logicalDpiY() );
50 }
51 
52 
54 
55 
56 //
57 // QgsSimpleMarkerSymbolLayerBase
58 //
59 
60 QList<QgsSimpleMarkerSymbolLayerBase::Shape> QgsSimpleMarkerSymbolLayerBase::availableShapes()
61 {
62  QList< Shape > shapes;
63  shapes << Square
64  << Diamond
65  << Pentagon
66  << Hexagon
67  << Triangle
69  << Star
70  << Arrow
71  << Circle
72  << Cross
73  << CrossFill
74  << Cross2
75  << Line
76  << ArrowHead
78  << SemiCircle
79  << ThirdCircle
80  << QuarterCircle
81  << QuarterSquare
82  << HalfSquare
86  return shapes;
87 }
88 
90  : mShape( shape )
91 {
92  mSize = size;
93  mAngle = angle;
94  mOffset = QPointF( 0, 0 );
98 }
99 
101 {
102  switch ( shape )
103  {
104  case Square:
105  case Diamond:
106  case Pentagon:
107  case Hexagon:
108  case Triangle:
109  case EquilateralTriangle:
110  case Star:
111  case Arrow:
112  case Circle:
113  case CrossFill:
114  case ArrowHeadFilled:
115  case SemiCircle:
116  case ThirdCircle:
117  case QuarterCircle:
118  case QuarterSquare:
119  case HalfSquare:
120  case DiagonalHalfSquare:
121  case RightHalfTriangle:
122  case LeftHalfTriangle:
123  return true;
124 
125  case Cross:
126  case Cross2:
127  case Line:
128  case ArrowHead:
129  return false;
130  }
131  return true;
132 }
133 
135 {
136  bool hasDataDefinedRotation = context.renderHints() & QgsSymbol::DynamicRotation
138  bool hasDataDefinedSize = mDataDefinedProperties.isActive( QgsSymbolLayer::PropertySize );
139 
140  // use either QPolygonF or QPainterPath for drawing
141  if ( !prepareMarkerShape( mShape ) ) // drawing as a polygon
142  {
143  prepareMarkerPath( mShape ); // drawing as a painter path
144  }
145 
146  QTransform transform;
147 
148  // scale the shape (if the size is not going to be modified)
149  if ( !hasDataDefinedSize )
150  {
151  double scaledSize = context.renderContext().convertToPainterUnits( mSize, mSizeUnit, mSizeMapUnitScale );
153  {
154  // rendering for symbol previews -- an size in meters in map units can't be calculated, so treat the size as millimeters
155  // and clamp it to a reasonable range. It's the best we can do in this situation!
156  scaledSize = std::min( std::max( context.renderContext().convertToPainterUnits( mSize, QgsUnitTypes::RenderMillimeters ), 3.0 ), 100.0 );
157  }
158 
159  double half = scaledSize / 2.0;
160  transform.scale( half, half );
161  }
162 
163  // rotate if the rotation is not going to be changed during the rendering
164  if ( !hasDataDefinedRotation && !qgsDoubleNear( mAngle, 0.0 ) )
165  {
166  transform.rotate( mAngle );
167  }
168 
169  if ( !mPolygon.isEmpty() )
170  mPolygon = transform.map( mPolygon );
171  else
172  mPath = transform.map( mPath );
173 
175 }
176 
178 {
179  Q_UNUSED( context )
180 }
181 
183 {
184  //making changes here? Don't forget to also update ::bounds if the changes affect the bounding box
185  //of the rendered point!
186 
187  QPainter *p = context.renderContext().painter();
188  if ( !p )
189  {
190  return;
191  }
192 
193  bool hasDataDefinedSize = false;
194  double scaledSize = calculateSize( context, hasDataDefinedSize );
195 
196  bool hasDataDefinedRotation = false;
197  QPointF offset;
198  double angle = 0;
199  calculateOffsetAndRotation( context, scaledSize, hasDataDefinedRotation, offset, angle );
200 
201  //data defined shape?
202  bool createdNewPath = false;
203  bool ok = true;
204  Shape symbol = mShape;
206  {
207  context.setOriginalValueVariable( encodeShape( symbol ) );
209  if ( exprVal.isValid() )
210  {
211  Shape decoded = decodeShape( exprVal.toString(), &ok );
212  if ( ok )
213  {
214  symbol = decoded;
215 
216  if ( !prepareMarkerShape( symbol ) ) // drawing as a polygon
217  {
218  prepareMarkerPath( symbol ); // drawing as a painter path
219  }
220  createdNewPath = true;
221  }
222  }
223  else
224  {
225  symbol = mShape;
226  }
227  }
228 
229  QTransform transform;
230 
231  // move to the desired position
232  transform.translate( point.x() + offset.x(), point.y() + offset.y() );
233 
234  // resize if necessary
235  if ( hasDataDefinedSize || createdNewPath )
236  {
237  double s = context.renderContext().convertToPainterUnits( scaledSize, mSizeUnit, mSizeMapUnitScale );
239  {
240  // rendering for symbol previews -- a size in meters in map units can't be calculated, so treat the size as millimeters
241  // and clamp it to a reasonable range. It's the best we can do in this situation!
242  s = std::min( std::max( context.renderContext().convertToPainterUnits( mSize, QgsUnitTypes::RenderMillimeters ), 3.0 ), 100.0 );
243  }
244  double half = s / 2.0;
245  transform.scale( half, half );
246  }
247 
248  if ( !qgsDoubleNear( angle, 0.0 ) && ( hasDataDefinedRotation || createdNewPath ) )
249  transform.rotate( angle );
250 
251  //need to pass: symbol, polygon, path
252 
253  QPolygonF polygon;
254  QPainterPath path;
255  if ( !mPolygon.isEmpty() )
256  {
257  polygon = transform.map( mPolygon );
258  }
259  else
260  {
261  path = transform.map( mPath );
262  }
263  draw( context, symbol, polygon, path );
264 }
265 
267 {
268  bool hasDataDefinedSize = false;
269  double scaledSize = calculateSize( context, hasDataDefinedSize );
270 
271  bool hasDataDefinedRotation = false;
272  QPointF offset;
273  double angle = 0;
274  calculateOffsetAndRotation( context, scaledSize, hasDataDefinedRotation, offset, angle );
275 
276  scaledSize = context.renderContext().convertToPainterUnits( scaledSize, mSizeUnit, mSizeMapUnitScale );
277 
278  QTransform transform;
279 
280  // move to the desired position
281  transform.translate( point.x() + offset.x(), point.y() + offset.y() );
282 
283  if ( !qgsDoubleNear( angle, 0.0 ) )
284  transform.rotate( angle );
285 
286  return transform.mapRect( QRectF( -scaledSize / 2.0,
287  -scaledSize / 2.0,
288  scaledSize,
289  scaledSize ) );
290 }
291 
293 {
294  if ( ok )
295  *ok = true;
296  QString cleaned = name.toLower().trimmed();
297 
298  if ( cleaned == QLatin1String( "square" ) || cleaned == QLatin1String( "rectangle" ) )
299  return Square;
300  else if ( cleaned == QLatin1String( "diamond" ) )
301  return Diamond;
302  else if ( cleaned == QLatin1String( "pentagon" ) )
303  return Pentagon;
304  else if ( cleaned == QLatin1String( "hexagon" ) )
305  return Hexagon;
306  else if ( cleaned == QLatin1String( "triangle" ) )
307  return Triangle;
308  else if ( cleaned == QLatin1String( "equilateral_triangle" ) )
309  return EquilateralTriangle;
310  else if ( cleaned == QLatin1String( "star" ) || cleaned == QLatin1String( "regular_star" ) )
311  return Star;
312  else if ( cleaned == QLatin1String( "arrow" ) )
313  return Arrow;
314  else if ( cleaned == QLatin1String( "circle" ) )
315  return Circle;
316  else if ( cleaned == QLatin1String( "cross" ) )
317  return Cross;
318  else if ( cleaned == QLatin1String( "cross_fill" ) )
319  return CrossFill;
320  else if ( cleaned == QLatin1String( "cross2" ) || cleaned == QLatin1String( "x" ) )
321  return Cross2;
322  else if ( cleaned == QLatin1String( "line" ) )
323  return Line;
324  else if ( cleaned == QLatin1String( "arrowhead" ) )
325  return ArrowHead;
326  else if ( cleaned == QLatin1String( "filled_arrowhead" ) )
327  return ArrowHeadFilled;
328  else if ( cleaned == QLatin1String( "semi_circle" ) )
329  return SemiCircle;
330  else if ( cleaned == QLatin1String( "third_circle" ) )
331  return ThirdCircle;
332  else if ( cleaned == QLatin1String( "quarter_circle" ) )
333  return QuarterCircle;
334  else if ( cleaned == QLatin1String( "quarter_square" ) )
335  return QuarterSquare;
336  else if ( cleaned == QLatin1String( "half_square" ) )
337  return HalfSquare;
338  else if ( cleaned == QLatin1String( "diagonal_half_square" ) )
339  return DiagonalHalfSquare;
340  else if ( cleaned == QLatin1String( "right_half_triangle" ) )
341  return RightHalfTriangle;
342  else if ( cleaned == QLatin1String( "left_half_triangle" ) )
343  return LeftHalfTriangle;
344 
345  if ( ok )
346  *ok = false;
347  return Circle;
348 }
349 
351 {
352  switch ( shape )
353  {
354  case Square:
355  return QStringLiteral( "square" );
356  case QuarterSquare:
357  return QStringLiteral( "quarter_square" );
358  case HalfSquare:
359  return QStringLiteral( "half_square" );
360  case DiagonalHalfSquare:
361  return QStringLiteral( "diagonal_half_square" );
362  case Diamond:
363  return QStringLiteral( "diamond" );
364  case Pentagon:
365  return QStringLiteral( "pentagon" );
366  case Hexagon:
367  return QStringLiteral( "hexagon" );
368  case Triangle:
369  return QStringLiteral( "triangle" );
370  case EquilateralTriangle:
371  return QStringLiteral( "equilateral_triangle" );
372  case LeftHalfTriangle:
373  return QStringLiteral( "left_half_triangle" );
374  case RightHalfTriangle:
375  return QStringLiteral( "right_half_triangle" );
376  case Star:
377  return QStringLiteral( "star" );
378  case Arrow:
379  return QStringLiteral( "arrow" );
380  case ArrowHeadFilled:
381  return QStringLiteral( "filled_arrowhead" );
382  case CrossFill:
383  return QStringLiteral( "cross_fill" );
384  case Circle:
385  return QStringLiteral( "circle" );
386  case Cross:
387  return QStringLiteral( "cross" );
388  case Cross2:
389  return QStringLiteral( "cross2" );
390  case Line:
391  return QStringLiteral( "line" );
392  case ArrowHead:
393  return QStringLiteral( "arrowhead" );
394  case SemiCircle:
395  return QStringLiteral( "semi_circle" );
396  case ThirdCircle:
397  return QStringLiteral( "third_circle" );
398  case QuarterCircle:
399  return QStringLiteral( "quarter_circle" );
400  }
401  return QString();
402 }
403 
405 {
406  return shapeToPolygon( shape, mPolygon );
407 }
408 
410 {
411  polygon.clear();
412 
413  switch ( shape )
414  {
415  case Square:
416  polygon = QPolygonF( QRectF( QPointF( -1, -1 ), QPointF( 1, 1 ) ) );
417  return true;
418 
419  case QuarterSquare:
420  polygon = QPolygonF( QRectF( QPointF( -1, -1 ), QPointF( 0, 0 ) ) );
421  return true;
422 
423  case HalfSquare:
424  polygon = QPolygonF( QRectF( QPointF( -1, -1 ), QPointF( 0, 1 ) ) );
425  return true;
426 
427  case DiagonalHalfSquare:
428  polygon << QPointF( -1, -1 ) << QPointF( 1, 1 ) << QPointF( -1, 1 ) << QPointF( -1, -1 );
429  return true;
430 
431  case Diamond:
432  polygon << QPointF( -1, 0 ) << QPointF( 0, 1 )
433  << QPointF( 1, 0 ) << QPointF( 0, -1 ) << QPointF( -1, 0 );
434  return true;
435 
436  case Pentagon:
437  /* angular-representation of hardcoded values used
438  polygon << QPointF( std::sin( DEG2RAD( 288.0 ) ), - std::cos( DEG2RAD( 288.0 ) ) )
439  << QPointF( std::sin( DEG2RAD( 216.0 ) ), - std::cos( DEG2RAD( 216.0 ) ) )
440  << QPointF( std::sin( DEG2RAD( 144.0 ) ), - std::cos( DEG2RAD( 144.0 ) ) )
441  << QPointF( std::sin( DEG2RAD( 72.0 ) ), - std::cos( DEG2RAD( 72.0 ) ) )
442  << QPointF( 0, -1 ); */
443  polygon << QPointF( -0.9511, -0.3090 )
444  << QPointF( -0.5878, 0.8090 )
445  << QPointF( 0.5878, 0.8090 )
446  << QPointF( 0.9511, -0.3090 )
447  << QPointF( 0, -1 )
448  << QPointF( -0.9511, -0.3090 );
449  return true;
450 
451  case Hexagon:
452  /* angular-representation of hardcoded values used
453  polygon << QPointF( std::sin( DEG2RAD( 300.0 ) ), - std::cos( DEG2RAD( 300.0 ) ) )
454  << QPointF( std::sin( DEG2RAD( 240.0 ) ), - std::cos( DEG2RAD( 240.0 ) ) )
455  << QPointF( std::sin( DEG2RAD( 180.0 ) ), - std::cos( DEG2RAD( 180.0 ) ) )
456  << QPointF( std::sin( DEG2RAD( 120.0 ) ), - std::cos( DEG2RAD( 120.0 ) ) )
457  << QPointF( std::sin( DEG2RAD( 60.0 ) ), - std::cos( DEG2RAD( 60.0 ) ) )
458  << QPointF( 0, -1 ); */
459  polygon << QPointF( -0.8660, -0.5 )
460  << QPointF( -0.8660, 0.5 )
461  << QPointF( 0, 1 )
462  << QPointF( 0.8660, 0.5 )
463  << QPointF( 0.8660, -0.5 )
464  << QPointF( 0, -1 )
465  << QPointF( -0.8660, -0.5 );
466  return true;
467 
468  case Triangle:
469  polygon << QPointF( -1, 1 ) << QPointF( 1, 1 ) << QPointF( 0, -1 ) << QPointF( -1, 1 );
470  return true;
471 
472  case EquilateralTriangle:
473  /* angular-representation of hardcoded values used
474  polygon << QPointF( std::sin( DEG2RAD( 240.0 ) ), - std::cos( DEG2RAD( 240.0 ) ) )
475  << QPointF( std::sin( DEG2RAD( 120.0 ) ), - std::cos( DEG2RAD( 120.0 ) ) )
476  << QPointF( 0, -1 ); */
477  polygon << QPointF( -0.8660, 0.5 )
478  << QPointF( 0.8660, 0.5 )
479  << QPointF( 0, -1 )
480  << QPointF( -0.8660, 0.5 );
481  return true;
482 
483  case LeftHalfTriangle:
484  polygon << QPointF( 0, 1 ) << QPointF( 1, 1 ) << QPointF( 0, -1 ) << QPointF( 0, 1 );
485  return true;
486 
487  case RightHalfTriangle:
488  polygon << QPointF( -1, 1 ) << QPointF( 0, 1 ) << QPointF( 0, -1 ) << QPointF( -1, 1 );
489  return true;
490 
491  case Star:
492  {
493  double inner_r = std::cos( DEG2RAD( 72.0 ) ) / std::cos( DEG2RAD( 36.0 ) );
494 
495  polygon << QPointF( inner_r * std::sin( DEG2RAD( 324.0 ) ), - inner_r * std::cos( DEG2RAD( 324.0 ) ) ) // 324
496  << QPointF( std::sin( DEG2RAD( 288.0 ) ), - std::cos( DEG2RAD( 288 ) ) ) // 288
497  << QPointF( inner_r * std::sin( DEG2RAD( 252.0 ) ), - inner_r * std::cos( DEG2RAD( 252.0 ) ) ) // 252
498  << QPointF( std::sin( DEG2RAD( 216.0 ) ), - std::cos( DEG2RAD( 216.0 ) ) ) // 216
499  << QPointF( 0, inner_r ) // 180
500  << QPointF( std::sin( DEG2RAD( 144.0 ) ), - std::cos( DEG2RAD( 144.0 ) ) ) // 144
501  << QPointF( inner_r * std::sin( DEG2RAD( 108.0 ) ), - inner_r * std::cos( DEG2RAD( 108.0 ) ) ) // 108
502  << QPointF( std::sin( DEG2RAD( 72.0 ) ), - std::cos( DEG2RAD( 72.0 ) ) ) // 72
503  << QPointF( inner_r * std::sin( DEG2RAD( 36.0 ) ), - inner_r * std::cos( DEG2RAD( 36.0 ) ) ) // 36
504  << QPointF( 0, -1 )
505  << QPointF( inner_r * std::sin( DEG2RAD( 324.0 ) ), - inner_r * std::cos( DEG2RAD( 324.0 ) ) ); // 324; // 0
506  return true;
507  }
508 
509  case Arrow:
510  polygon << QPointF( 0, -1 )
511  << QPointF( 0.5, -0.5 )
512  << QPointF( 0.25, -0.5 )
513  << QPointF( 0.25, 1 )
514  << QPointF( -0.25, 1 )
515  << QPointF( -0.25, -0.5 )
516  << QPointF( -0.5, -0.5 )
517  << QPointF( 0, -1 );
518  return true;
519 
520  case ArrowHeadFilled:
521  polygon << QPointF( 0, 0 ) << QPointF( -1, 1 ) << QPointF( -1, -1 ) << QPointF( 0, 0 );
522  return true;
523 
524  case CrossFill:
525  polygon << QPointF( -1, -0.2 )
526  << QPointF( -1, -0.2 )
527  << QPointF( -1, 0.2 )
528  << QPointF( -0.2, 0.2 )
529  << QPointF( -0.2, 1 )
530  << QPointF( 0.2, 1 )
531  << QPointF( 0.2, 0.2 )
532  << QPointF( 1, 0.2 )
533  << QPointF( 1, -0.2 )
534  << QPointF( 0.2, -0.2 )
535  << QPointF( 0.2, -1 )
536  << QPointF( -0.2, -1 )
537  << QPointF( -0.2, -0.2 )
538  << QPointF( -1, -0.2 );
539  return true;
540 
541  case Circle:
542  case Cross:
543  case Cross2:
544  case Line:
545  case ArrowHead:
546  case SemiCircle:
547  case ThirdCircle:
548  case QuarterCircle:
549  return false;
550  }
551 
552  return false;
553 }
554 
556 {
557  mPath = QPainterPath();
558 
559  switch ( symbol )
560  {
561  case Circle:
562 
563  mPath.addEllipse( QRectF( -1, -1, 2, 2 ) ); // x,y,w,h
564  return true;
565 
566  case SemiCircle:
567  mPath.arcTo( -1, -1, 2, 2, 0, 180 );
568  mPath.lineTo( 0, 0 );
569  return true;
570 
571  case ThirdCircle:
572  mPath.arcTo( -1, -1, 2, 2, 90, 120 );
573  mPath.lineTo( 0, 0 );
574  return true;
575 
576  case QuarterCircle:
577  mPath.arcTo( -1, -1, 2, 2, 90, 90 );
578  mPath.lineTo( 0, 0 );
579  return true;
580 
581  case Cross:
582  mPath.moveTo( -1, 0 );
583  mPath.lineTo( 1, 0 ); // horizontal
584  mPath.moveTo( 0, -1 );
585  mPath.lineTo( 0, 1 ); // vertical
586  return true;
587 
588  case Cross2:
589  mPath.moveTo( -1, -1 );
590  mPath.lineTo( 1, 1 );
591  mPath.moveTo( 1, -1 );
592  mPath.lineTo( -1, 1 );
593  return true;
594 
595  case Line:
596  mPath.moveTo( 0, -1 );
597  mPath.lineTo( 0, 1 ); // vertical line
598  return true;
599 
600  case ArrowHead:
601  mPath.moveTo( -1, -1 );
602  mPath.lineTo( 0, 0 );
603  mPath.lineTo( -1, 1 );
604  return true;
605 
606  case Square:
607  case QuarterSquare:
608  case HalfSquare:
609  case DiagonalHalfSquare:
610  case Diamond:
611  case Pentagon:
612  case Hexagon:
613  case Triangle:
614  case EquilateralTriangle:
615  case LeftHalfTriangle:
616  case RightHalfTriangle:
617  case Star:
618  case Arrow:
619  case ArrowHeadFilled:
620  case CrossFill:
621  return false;
622  }
623  return false;
624 }
625 
626 double QgsSimpleMarkerSymbolLayerBase::calculateSize( QgsSymbolRenderContext &context, bool &hasDataDefinedSize ) const
627 {
628  double scaledSize = mSize;
629 
631  bool ok = true;
632  if ( hasDataDefinedSize )
633  {
634  context.setOriginalValueVariable( mSize );
636  mSize, &ok );
637  }
638 
639  if ( hasDataDefinedSize && ok )
640  {
641  switch ( mScaleMethod )
642  {
644  scaledSize = std::sqrt( scaledSize );
645  break;
647  break;
648  }
649  }
650 
651  return scaledSize;
652 }
653 
654 void QgsSimpleMarkerSymbolLayerBase::calculateOffsetAndRotation( QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedRotation, QPointF &offset, double &angle ) const
655 {
656  //offset
657  double offsetX = 0;
658  double offsetY = 0;
659  markerOffset( context, scaledSize, scaledSize, offsetX, offsetY );
660  offset = QPointF( offsetX, offsetY );
661 
662  hasDataDefinedRotation = false;
663  //angle
664  bool ok = true;
665  angle = mAngle + mLineAngle;
667  {
668  context.setOriginalValueVariable( angle );
670 
671  // If the expression evaluation was not successful, fallback to static value
672  if ( !ok )
673  angle = mAngle + mLineAngle;
674 
675  hasDataDefinedRotation = true;
676  }
677 
678  hasDataDefinedRotation = context.renderHints() & QgsSymbol::DynamicRotation || hasDataDefinedRotation;
679 
680  if ( hasDataDefinedRotation )
681  {
682  // For non-point markers, "dataDefinedRotation" means following the
683  // shape (shape-data defined). For them, "field-data defined" does
684  // not work at all. TODO: if "field-data defined" ever gets implemented
685  // we'll need a way to distinguish here between the two, possibly
686  // using another flag in renderHints()
687  const QgsFeature *f = context.feature();
688  if ( f )
689  {
690  if ( f->hasGeometry() && f->geometry().type() == QgsWkbTypes::PointGeometry )
691  {
692  const QgsMapToPixel &m2p = context.renderContext().mapToPixel();
693  angle += m2p.mapRotation();
694  }
695  }
696  }
697 
698  if ( angle )
700 }
701 
702 
703 //
704 // QgsSimpleMarkerSymbolLayer
705 //
706 
707 QgsSimpleMarkerSymbolLayer::QgsSimpleMarkerSymbolLayer( QgsSimpleMarkerSymbolLayerBase::Shape shape, double size, double angle, QgsSymbol::ScaleMethod scaleMethod, const QColor &color, const QColor &strokeColor, Qt::PenJoinStyle penJoinStyle )
708  : QgsSimpleMarkerSymbolLayerBase( shape, size, angle, scaleMethod )
709  , mStrokeColor( strokeColor )
710  , mPenJoinStyle( penJoinStyle )
711 {
712  mColor = color;
713 }
714 
716 {
717  Shape shape = Circle;
720  Qt::PenJoinStyle penJoinStyle = DEFAULT_SIMPLEMARKER_JOINSTYLE;
724 
725  if ( props.contains( QStringLiteral( "name" ) ) )
726  {
727  shape = decodeShape( props[QStringLiteral( "name" )] );
728  }
729  if ( props.contains( QStringLiteral( "color" ) ) )
730  color = QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "color" )] );
731  if ( props.contains( QStringLiteral( "color_border" ) ) )
732  {
733  //pre 2.5 projects use "color_border"
734  strokeColor = QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "color_border" )] );
735  }
736  else if ( props.contains( QStringLiteral( "outline_color" ) ) )
737  {
738  strokeColor = QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "outline_color" )] );
739  }
740  else if ( props.contains( QStringLiteral( "line_color" ) ) )
741  {
742  strokeColor = QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "line_color" )] );
743  }
744  if ( props.contains( QStringLiteral( "joinstyle" ) ) )
745  {
746  penJoinStyle = QgsSymbolLayerUtils::decodePenJoinStyle( props[QStringLiteral( "joinstyle" )] );
747  }
748  if ( props.contains( QStringLiteral( "size" ) ) )
749  size = props[QStringLiteral( "size" )].toDouble();
750  if ( props.contains( QStringLiteral( "angle" ) ) )
751  angle = props[QStringLiteral( "angle" )].toDouble();
752  if ( props.contains( QStringLiteral( "scale_method" ) ) )
753  scaleMethod = QgsSymbolLayerUtils::decodeScaleMethod( props[QStringLiteral( "scale_method" )] );
754 
756  if ( props.contains( QStringLiteral( "offset" ) ) )
757  m->setOffset( QgsSymbolLayerUtils::decodePoint( props[QStringLiteral( "offset" )] ) );
758  if ( props.contains( QStringLiteral( "offset_unit" ) ) )
759  m->setOffsetUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "offset_unit" )] ) );
760  if ( props.contains( QStringLiteral( "offset_map_unit_scale" ) ) )
761  m->setOffsetMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "offset_map_unit_scale" )] ) );
762  if ( props.contains( QStringLiteral( "size_unit" ) ) )
763  m->setSizeUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "size_unit" )] ) );
764  if ( props.contains( QStringLiteral( "size_map_unit_scale" ) ) )
765  m->setSizeMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "size_map_unit_scale" )] ) );
766 
767  if ( props.contains( QStringLiteral( "outline_style" ) ) )
768  {
769  m->setStrokeStyle( QgsSymbolLayerUtils::decodePenStyle( props[QStringLiteral( "outline_style" )] ) );
770  }
771  else if ( props.contains( QStringLiteral( "line_style" ) ) )
772  {
773  m->setStrokeStyle( QgsSymbolLayerUtils::decodePenStyle( props[QStringLiteral( "line_style" )] ) );
774  }
775  if ( props.contains( QStringLiteral( "outline_width" ) ) )
776  {
777  m->setStrokeWidth( props[QStringLiteral( "outline_width" )].toDouble() );
778  }
779  else if ( props.contains( QStringLiteral( "line_width" ) ) )
780  {
781  m->setStrokeWidth( props[QStringLiteral( "line_width" )].toDouble() );
782  }
783  if ( props.contains( QStringLiteral( "outline_width_unit" ) ) )
784  {
785  m->setStrokeWidthUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "outline_width_unit" )] ) );
786  }
787  if ( props.contains( QStringLiteral( "line_width_unit" ) ) )
788  {
789  m->setStrokeWidthUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "line_width_unit" )] ) );
790  }
791  if ( props.contains( QStringLiteral( "outline_width_map_unit_scale" ) ) )
792  {
793  m->setStrokeWidthMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "outline_width_map_unit_scale" )] ) );
794  }
795 
796  if ( props.contains( QStringLiteral( "horizontal_anchor_point" ) ) )
797  {
798  m->setHorizontalAnchorPoint( QgsMarkerSymbolLayer::HorizontalAnchorPoint( props[ QStringLiteral( "horizontal_anchor_point" )].toInt() ) );
799  }
800  if ( props.contains( QStringLiteral( "vertical_anchor_point" ) ) )
801  {
802  m->setVerticalAnchorPoint( QgsMarkerSymbolLayer::VerticalAnchorPoint( props[ QStringLiteral( "vertical_anchor_point" )].toInt() ) );
803  }
804 
806 
807  return m;
808 }
809 
810 
812 {
813  return QStringLiteral( "SimpleMarker" );
814 }
815 
817 {
819 
820  QColor brushColor = mColor;
821  QColor penColor = mStrokeColor;
822 
823  brushColor.setAlphaF( mColor.alphaF() * context.opacity() );
824  penColor.setAlphaF( mStrokeColor.alphaF() * context.opacity() );
825 
826  mBrush = QBrush( brushColor );
827  mPen = QPen( penColor );
828  mPen.setStyle( mStrokeStyle );
829  mPen.setJoinStyle( mPenJoinStyle );
831 
832  QColor selBrushColor = context.renderContext().selectionColor();
833  QColor selPenColor = selBrushColor == mColor ? selBrushColor : mStrokeColor;
834  if ( context.opacity() < 1 && !SELECTION_IS_OPAQUE )
835  {
836  selBrushColor.setAlphaF( context.opacity() );
837  selPenColor.setAlphaF( context.opacity() );
838  }
839  mSelBrush = QBrush( selBrushColor );
840  mSelPen = QPen( selPenColor );
841  mSelPen.setStyle( mStrokeStyle );
843 
845  bool hasDataDefinedSize = mDataDefinedProperties.isActive( QgsSymbolLayer::PropertySize );
846 
847  // use caching only when:
848  // - size, rotation, shape, color, stroke color is not data-defined
849  // - drawing to screen (not printer)
850  mUsingCache = !hasDataDefinedRotation && !hasDataDefinedSize && !context.renderContext().forceVectorOutput()
854 
855  if ( !shapeIsFilled( mShape ) )
856  {
857  // some markers can't be drawn as a polygon (circle, cross)
858  // For these set the selected stroke color to the selected color
859  mSelPen.setColor( selBrushColor );
860  }
861 
862 
863  if ( mUsingCache )
864  {
865  if ( !prepareCache( context ) )
866  {
867  mUsingCache = false;
868  }
869  }
870  else
871  {
872  mCache = QImage();
873  mSelCache = QImage();
874  }
875 }
876 
877 
879 {
880  double scaledSize = context.renderContext().convertToPainterUnits( mSize, mSizeUnit, mSizeMapUnitScale );
882  {
883  // rendering for symbol previews -- a size in meters in map units can't be calculated, so treat the size as millimeters
884  // and clamp it to a reasonable range. It's the best we can do in this situation!
885  scaledSize = std::min( std::max( context.renderContext().convertToPainterUnits( mSize, QgsUnitTypes::RenderMillimeters ), 3.0 ), 100.0 );
886  }
887 
888  // take into account angle (which is not data-defined otherwise cache wouldn't be used)
889  if ( !qgsDoubleNear( mAngle, 0.0 ) )
890  {
891  scaledSize = ( std::abs( std::sin( mAngle * M_PI / 180 ) ) + std::abs( std::cos( mAngle * M_PI / 180 ) ) ) * scaledSize;
892  }
893  // calculate necessary image size for the cache
894  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
895  int imageSize = ( static_cast< int >( scaledSize ) + pw ) / 2 * 2 + 1; // make image width, height odd; account for pen width
896  double center = imageSize / 2.0;
897  if ( imageSize > MAXIMUM_CACHE_WIDTH )
898  {
899  return false;
900  }
901 
902  mCache = QImage( QSize( imageSize, imageSize ), QImage::Format_ARGB32_Premultiplied );
903  mCache.fill( 0 );
904 
905  bool needsBrush = shapeIsFilled( mShape );
906 
907  QPainter p;
908  p.begin( &mCache );
909  p.setRenderHint( QPainter::Antialiasing );
910  p.setBrush( needsBrush ? mBrush : Qt::NoBrush );
911  p.setPen( mPen );
912  p.translate( QPointF( center, center ) );
913  drawMarker( &p, context );
914  p.end();
915 
916  // Construct the selected version of the Cache
917 
918  QColor selColor = context.renderContext().selectionColor();
919 
920  mSelCache = QImage( QSize( imageSize, imageSize ), QImage::Format_ARGB32_Premultiplied );
921  mSelCache.fill( 0 );
922 
923  p.begin( &mSelCache );
924  p.setRenderHint( QPainter::Antialiasing );
925  p.setBrush( needsBrush ? mSelBrush : Qt::NoBrush );
926  p.setPen( mSelPen );
927  p.translate( QPointF( center, center ) );
928  drawMarker( &p, context );
929  p.end();
930 
931  // Check that the selected version is different. If not, then re-render,
932  // filling the background with the selection color and using the normal
933  // colors for the symbol .. could be ugly!
934 
935  if ( mSelCache == mCache )
936  {
937  p.begin( &mSelCache );
938  p.setRenderHint( QPainter::Antialiasing );
939  p.fillRect( 0, 0, imageSize, imageSize, selColor );
940  p.setBrush( needsBrush ? mBrush : Qt::NoBrush );
941  p.setPen( mPen );
942  p.translate( QPointF( center, center ) );
943  drawMarker( &p, context );
944  p.end();
945  }
946 
947  return true;
948 }
949 
950 void QgsSimpleMarkerSymbolLayer::draw( QgsSymbolRenderContext &context, QgsSimpleMarkerSymbolLayerBase::Shape shape, const QPolygonF &polygon, const QPainterPath &path )
951 {
952  //making changes here? Don't forget to also update ::bounds if the changes affect the bounding box
953  //of the rendered point!
954 
955  QPainter *p = context.renderContext().painter();
956  if ( !p )
957  {
958  return;
959  }
960 
961  bool ok = true;
963  {
966  if ( ok )
967  mBrush.setColor( c );
968  }
970  {
973  if ( ok )
974  {
975  mPen.setColor( c );
976  mSelPen.setColor( c );
977  }
978  }
980  {
983  if ( ok )
984  {
987  }
988  }
990  {
993  if ( ok )
994  {
997  }
998  }
1000  {
1003  if ( ok )
1004  {
1005  mPen.setJoinStyle( QgsSymbolLayerUtils::decodePenJoinStyle( style ) );
1006  mSelPen.setJoinStyle( QgsSymbolLayerUtils::decodePenJoinStyle( style ) );
1007  }
1008  }
1009 
1010  if ( shapeIsFilled( shape ) )
1011  {
1012  p->setBrush( context.selected() ? mSelBrush : mBrush );
1013  }
1014  else
1015  {
1016  p->setBrush( Qt::NoBrush );
1017  }
1018  p->setPen( context.selected() ? mSelPen : mPen );
1019 
1020  if ( !polygon.isEmpty() )
1021  p->drawPolygon( polygon );
1022  else
1023  p->drawPath( path );
1024 }
1025 
1027 {
1028  //making changes here? Don't forget to also update ::bounds if the changes affect the bounding box
1029  //of the rendered point!
1030 
1031  QPainter *p = context.renderContext().painter();
1032  if ( !p )
1033  {
1034  return;
1035  }
1036 
1037  if ( mUsingCache )
1038  {
1039  QImage &img = context.selected() ? mSelCache : mCache;
1040  double s = img.width();
1041 
1042  bool hasDataDefinedSize = false;
1043  double scaledSize = calculateSize( context, hasDataDefinedSize );
1044 
1045  bool hasDataDefinedRotation = false;
1046  QPointF offset;
1047  double angle = 0;
1048  calculateOffsetAndRotation( context, scaledSize, hasDataDefinedRotation, offset, angle );
1049 
1050  p->drawImage( QRectF( point.x() - s / 2.0 + offset.x(),
1051  point.y() - s / 2.0 + offset.y(),
1052  s, s ), img );
1053  }
1054  else
1055  {
1057  }
1058 }
1059 
1061 {
1062  QgsStringMap map;
1063  map[QStringLiteral( "name" )] = encodeShape( mShape );
1064  map[QStringLiteral( "color" )] = QgsSymbolLayerUtils::encodeColor( mColor );
1065  map[QStringLiteral( "outline_color" )] = QgsSymbolLayerUtils::encodeColor( mStrokeColor );
1066  map[QStringLiteral( "size" )] = QString::number( mSize );
1067  map[QStringLiteral( "size_unit" )] = QgsUnitTypes::encodeUnit( mSizeUnit );
1068  map[QStringLiteral( "size_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mSizeMapUnitScale );
1069  map[QStringLiteral( "angle" )] = QString::number( mAngle );
1070  map[QStringLiteral( "offset" )] = QgsSymbolLayerUtils::encodePoint( mOffset );
1071  map[QStringLiteral( "offset_unit" )] = QgsUnitTypes::encodeUnit( mOffsetUnit );
1072  map[QStringLiteral( "offset_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mOffsetMapUnitScale );
1073  map[QStringLiteral( "scale_method" )] = QgsSymbolLayerUtils::encodeScaleMethod( mScaleMethod );
1074  map[QStringLiteral( "outline_style" )] = QgsSymbolLayerUtils::encodePenStyle( mStrokeStyle );
1075  map[QStringLiteral( "outline_width" )] = QString::number( mStrokeWidth );
1076  map[QStringLiteral( "outline_width_unit" )] = QgsUnitTypes::encodeUnit( mStrokeWidthUnit );
1077  map[QStringLiteral( "outline_width_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mStrokeWidthMapUnitScale );
1078  map[QStringLiteral( "joinstyle" )] = QgsSymbolLayerUtils::encodePenJoinStyle( mPenJoinStyle );
1079  map[QStringLiteral( "horizontal_anchor_point" )] = QString::number( mHorizontalAnchorPoint );
1080  map[QStringLiteral( "vertical_anchor_point" )] = QString::number( mVerticalAnchorPoint );
1081  return map;
1082 }
1083 
1085 {
1087  m->setOffset( mOffset );
1088  m->setSizeUnit( mSizeUnit );
1090  m->setOffsetUnit( mOffsetUnit );
1099  copyPaintEffect( m );
1100  return m;
1101 }
1102 
1103 void QgsSimpleMarkerSymbolLayer::writeSldMarker( QDomDocument &doc, QDomElement &element, const QgsStringMap &props ) const
1104 {
1105  // <Graphic>
1106  QDomElement graphicElem = doc.createElement( QStringLiteral( "se:Graphic" ) );
1107  element.appendChild( graphicElem );
1108 
1112 
1113  // <Rotation>
1114  QString angleFunc;
1115  bool ok;
1116  double angle = props.value( QStringLiteral( "angle" ), QStringLiteral( "0" ) ).toDouble( &ok );
1117  if ( !ok )
1118  {
1119  angleFunc = QStringLiteral( "%1 + %2" ).arg( props.value( QStringLiteral( "angle" ), QStringLiteral( "0" ) ) ).arg( mAngle );
1120  }
1121  else if ( !qgsDoubleNear( angle + mAngle, 0.0 ) )
1122  {
1123  angleFunc = QString::number( angle + mAngle );
1124  }
1125  QgsSymbolLayerUtils::createRotationElement( doc, graphicElem, angleFunc );
1126 
1127  // <Displacement>
1130 }
1131 
1132 QString QgsSimpleMarkerSymbolLayer::ogrFeatureStyle( double mmScaleFactor, double mapUnitScaleFactor ) const
1133 {
1134  Q_UNUSED( mmScaleFactor )
1135  Q_UNUSED( mapUnitScaleFactor )
1136 #if 0
1137  QString ogrType = "3"; //default is circle
1138  if ( mName == "square" )
1139  {
1140  ogrType = "5";
1141  }
1142  else if ( mName == "triangle" )
1143  {
1144  ogrType = "7";
1145  }
1146  else if ( mName == "star" )
1147  {
1148  ogrType = "9";
1149  }
1150  else if ( mName == "circle" )
1151  {
1152  ogrType = "3";
1153  }
1154  else if ( mName == "cross" )
1155  {
1156  ogrType = "0";
1157  }
1158  else if ( mName == "x" || mName == "cross2" )
1159  {
1160  ogrType = "1";
1161  }
1162  else if ( mName == "line" )
1163  {
1164  ogrType = "10";
1165  }
1166 
1167  QString ogrString;
1168  ogrString.append( "SYMBOL(" );
1169  ogrString.append( "id:" );
1170  ogrString.append( '\"' );
1171  ogrString.append( "ogr-sym-" );
1172  ogrString.append( ogrType );
1173  ogrString.append( '\"' );
1174  ogrString.append( ",c:" );
1175  ogrString.append( mColor.name() );
1176  ogrString.append( ",o:" );
1177  ogrString.append( mStrokeColor.name() );
1178  ogrString.append( QString( ",s:%1mm" ).arg( mSize ) );
1179  ogrString.append( ')' );
1180  return ogrString;
1181 #endif //0
1182 
1183  QString ogrString;
1184  ogrString.append( "PEN(" );
1185  ogrString.append( "c:" );
1186  ogrString.append( mColor.name() );
1187  ogrString.append( ",w:" );
1188  ogrString.append( QString::number( mSize ) );
1189  ogrString.append( "mm" );
1190  ogrString.append( ")" );
1191  return ogrString;
1192 }
1193 
1195 {
1196  QgsDebugMsgLevel( QStringLiteral( "Entered." ), 4 );
1197 
1198  QDomElement graphicElem = element.firstChildElement( QStringLiteral( "Graphic" ) );
1199  if ( graphicElem.isNull() )
1200  return nullptr;
1201 
1202  QString name = QStringLiteral( "square" );
1203  QColor color, strokeColor;
1204  double strokeWidth, size;
1205  Qt::PenStyle strokeStyle;
1206 
1208  return nullptr;
1209 
1210  double angle = 0.0;
1211  QString angleFunc;
1212  if ( QgsSymbolLayerUtils::rotationFromSldElement( graphicElem, angleFunc ) )
1213  {
1214  bool ok;
1215  double d = angleFunc.toDouble( &ok );
1216  if ( ok )
1217  angle = d;
1218  }
1219 
1220  QPointF offset;
1222 
1223  Shape shape = decodeShape( name );
1224 
1225  QString uom = element.attribute( QStringLiteral( "uom" ) );
1229 
1231  m->setOutputUnit( QgsUnitTypes::RenderUnit::RenderPixels );
1232  m->setColor( color );
1234  m->setAngle( angle );
1235  m->setOffset( offset );
1238  return m;
1239 }
1240 
1242 {
1243  Q_UNUSED( context )
1244 
1245  if ( mPolygon.count() != 0 )
1246  {
1247  p->drawPolygon( mPolygon );
1248  }
1249  else
1250  {
1251  p->drawPath( mPath );
1252  }
1253 }
1254 
1255 bool QgsSimpleMarkerSymbolLayer::writeDxf( QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, QgsSymbolRenderContext &context, QPointF shift ) const
1256 {
1257  //data defined size?
1258  double size = mSize;
1259 
1260  bool hasDataDefinedSize = mDataDefinedProperties.isActive( QgsSymbolLayer::PropertySize );
1261 
1262  //data defined size
1263  bool ok = true;
1264  if ( hasDataDefinedSize )
1265  {
1267 
1268  if ( ok )
1269  {
1270  switch ( mScaleMethod )
1271  {
1272  case QgsSymbol::ScaleArea:
1273  size = std::sqrt( size );
1274  break;
1276  break;
1277  }
1278  }
1279 
1281  }
1282 
1284  {
1285  size *= mmMapUnitScaleFactor;
1286  }
1287 
1289  {
1291  }
1292  double halfSize = size / 2.0;
1293 
1294  //strokeWidth
1295  double strokeWidth = mStrokeWidth;
1296 
1298  {
1301  }
1304  {
1306  }
1307 
1308  //color
1309  QColor pc = mPen.color();
1310  QColor bc = mBrush.color();
1312  {
1315  }
1317  {
1320  }
1321 
1322  //offset
1323  double offsetX = 0;
1324  double offsetY = 0;
1325  markerOffset( context, offsetX, offsetY );
1326  offsetX *= context.renderContext().mapToPixel().mapUnitsPerPixel();
1327  offsetY *= context.renderContext().mapToPixel().mapUnitsPerPixel();
1328 
1329 
1330  QPointF off( offsetX, offsetY );
1331 
1332  //angle
1333  double angle = mAngle + mLineAngle;
1335  {
1336  context.setOriginalValueVariable( mAngle );
1338  }
1339 
1340  Shape shape = mShape;
1342  {
1344  QString shapeName = mDataDefinedProperties.valueAsString( QgsSymbolLayer::PropertyName, context.renderContext().expressionContext(), QString(), &ok );
1345  if ( ok )
1346  {
1347  shape = decodeShape( shapeName, &ok );
1348  if ( !ok )
1349  shape = mShape;
1350  }
1351  }
1352 
1353  if ( angle )
1354  off = _rotatedOffset( off, angle );
1355 
1357 
1358  QTransform t;
1359  t.translate( shift.x() + off.x(), shift.y() - off.y() );
1360 
1361  if ( !qgsDoubleNear( angle, 0.0 ) )
1362  t.rotate( angle );
1363 
1364  QPolygonF polygon;
1365  if ( shapeToPolygon( shape, polygon ) )
1366  {
1367  t.scale( halfSize, -halfSize );
1368 
1369  polygon = t.map( polygon );
1370 
1371  QgsPointSequence p;
1372  p.reserve( polygon.size() );
1373  for ( int i = 0; i < polygon.size(); i++ )
1374  {
1375  p << QgsPoint( polygon[i] );
1376  }
1377 
1378  if ( mBrush.style() != Qt::NoBrush )
1379  e.writePolygon( QgsRingSequence() << p, layerName, QStringLiteral( "SOLID" ), bc );
1380  if ( mPen.style() != Qt::NoPen )
1381  e.writePolyline( p, layerName, QStringLiteral( "CONTINUOUS" ), pc, strokeWidth );
1382  }
1383  else if ( shape == Circle )
1384  {
1385  shift += QPointF( off.x(), -off.y() );
1386  if ( mBrush.style() != Qt::NoBrush )
1387  e.writeFilledCircle( layerName, bc, QgsPoint( shift ), halfSize );
1388  if ( mPen.style() != Qt::NoPen )
1389  e.writeCircle( layerName, pc, QgsPoint( shift ), halfSize, QStringLiteral( "CONTINUOUS" ), strokeWidth );
1390  }
1391  else if ( shape == Line )
1392  {
1393  QPointF pt1 = t.map( QPointF( 0, -halfSize ) );
1394  QPointF pt2 = t.map( QPointF( 0, halfSize ) );
1395 
1396  if ( mPen.style() != Qt::NoPen )
1397  e.writeLine( QgsPoint( pt1 ), QgsPoint( pt2 ), layerName, QStringLiteral( "CONTINUOUS" ), pc, strokeWidth );
1398  }
1399  else if ( shape == Cross )
1400  {
1401  if ( mPen.style() != Qt::NoPen )
1402  {
1403  QPointF pt1 = t.map( QPointF( -halfSize, 0 ) );
1404  QPointF pt2 = t.map( QPointF( halfSize, 0 ) );
1405  QPointF pt3 = t.map( QPointF( 0, -halfSize ) );
1406  QPointF pt4 = t.map( QPointF( 0, halfSize ) );
1407 
1408  e.writeLine( QgsPoint( pt1 ), QgsPoint( pt2 ), layerName, QStringLiteral( "CONTINUOUS" ), pc, strokeWidth );
1409  e.writeLine( QgsPoint( pt3 ), QgsPoint( pt4 ), layerName, QStringLiteral( "CONTINUOUS" ), pc, strokeWidth );
1410  }
1411  }
1412  else if ( shape == Cross2 )
1413  {
1414  if ( mPen.style() != Qt::NoPen )
1415  {
1416  QPointF pt1 = t.map( QPointF( -halfSize, -halfSize ) );
1417  QPointF pt2 = t.map( QPointF( halfSize, halfSize ) );
1418  QPointF pt3 = t.map( QPointF( halfSize, -halfSize ) );
1419  QPointF pt4 = t.map( QPointF( -halfSize, halfSize ) );
1420 
1421  e.writeLine( QgsPoint( pt1 ), QgsPoint( pt2 ), layerName, QStringLiteral( "CONTINUOUS" ), pc, strokeWidth );
1422  e.writeLine( QgsPoint( pt3 ), QgsPoint( pt4 ), layerName, QStringLiteral( "CONTINUOUS" ), pc, strokeWidth );
1423  }
1424  }
1425  else if ( shape == ArrowHead )
1426  {
1427  if ( mPen.style() != Qt::NoPen )
1428  {
1429  QPointF pt1 = t.map( QPointF( -halfSize, halfSize ) );
1430  QPointF pt2 = t.map( QPointF( 0, 0 ) );
1431  QPointF pt3 = t.map( QPointF( -halfSize, -halfSize ) );
1432 
1433  e.writeLine( QgsPoint( pt1 ), QgsPoint( pt2 ), layerName, QStringLiteral( "CONTINUOUS" ), pc, strokeWidth );
1434  e.writeLine( QgsPoint( pt3 ), QgsPoint( pt2 ), layerName, QStringLiteral( "CONTINUOUS" ), pc, strokeWidth );
1435  }
1436  }
1437  else
1438  {
1439  QgsDebugMsg( QStringLiteral( "Unsupported dxf marker name %1" ).arg( encodeShape( shape ) ) );
1440  return false;
1441  }
1442 
1443  return true;
1444 }
1445 
1446 
1448 {
1450  mStrokeWidthUnit = unit;
1451 }
1452 
1454 {
1456  {
1457  return mStrokeWidthUnit;
1458  }
1460 }
1461 
1463 {
1465  mStrokeWidthMapUnitScale = scale;
1466 }
1467 
1469 {
1471  {
1472  return mStrokeWidthMapUnitScale;
1473  }
1474  return QgsMapUnitScale();
1475 }
1476 
1478 {
1479  QRectF symbolBounds = QgsSimpleMarkerSymbolLayerBase::bounds( point, context );
1480 
1481  // need to account for stroke width
1482  double penWidth = mStrokeWidth;
1483  bool ok = true;
1485  {
1488  if ( ok )
1489  {
1490  penWidth = strokeWidth;
1491  }
1492  }
1495  {
1498  if ( ok && strokeStyle == QLatin1String( "no" ) )
1499  {
1500  penWidth = 0.0;
1501  }
1502  }
1503  else if ( mStrokeStyle == Qt::NoPen )
1504  penWidth = 0;
1505 
1506  //antialiasing, add 1 pixel
1507  penWidth += 1;
1508 
1509  //extend bounds by pen width / 2.0
1510  symbolBounds.adjust( -penWidth / 2.0, -penWidth / 2.0,
1511  penWidth / 2.0, penWidth / 2.0 );
1512 
1513  return symbolBounds;
1514 }
1515 
1516 void QgsSimpleMarkerSymbolLayer::setColor( const QColor &color )
1517 {
1518  if ( shapeIsFilled( mShape ) )
1519  {
1520  setFillColor( color );
1521  }
1522  else
1523  {
1524  setStrokeColor( color );
1525  }
1526 }
1527 
1529 {
1530  if ( shapeIsFilled( mShape ) )
1531  {
1532  return fillColor();
1533  }
1534  else
1535  {
1536  return strokeColor();
1537  }
1538 }
1539 
1540 
1541 
1542 
1543 //
1544 // QgsFilledMarkerSymbolLayer
1545 //
1546 
1548  : QgsSimpleMarkerSymbolLayerBase( shape, size, angle, scaleMethod )
1549 {
1550  mFill.reset( static_cast<QgsFillSymbol *>( QgsFillSymbol::createSimple( QgsStringMap() ) ) );
1551 }
1552 
1554 {
1555  QString name = DEFAULT_SIMPLEMARKER_NAME;
1559 
1560  if ( props.contains( QStringLiteral( "name" ) ) )
1561  name = props[QStringLiteral( "name" )];
1562  if ( props.contains( QStringLiteral( "size" ) ) )
1563  size = props[QStringLiteral( "size" )].toDouble();
1564  if ( props.contains( QStringLiteral( "angle" ) ) )
1565  angle = props[QStringLiteral( "angle" )].toDouble();
1566  if ( props.contains( QStringLiteral( "scale_method" ) ) )
1567  scaleMethod = QgsSymbolLayerUtils::decodeScaleMethod( props[QStringLiteral( "scale_method" )] );
1568 
1570  if ( props.contains( QStringLiteral( "offset" ) ) )
1571  m->setOffset( QgsSymbolLayerUtils::decodePoint( props[QStringLiteral( "offset" )] ) );
1572  if ( props.contains( QStringLiteral( "offset_unit" ) ) )
1573  m->setOffsetUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "offset_unit" )] ) );
1574  if ( props.contains( QStringLiteral( "offset_map_unit_scale" ) ) )
1575  m->setOffsetMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "offset_map_unit_scale" )] ) );
1576  if ( props.contains( QStringLiteral( "size_unit" ) ) )
1577  m->setSizeUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "size_unit" )] ) );
1578  if ( props.contains( QStringLiteral( "size_map_unit_scale" ) ) )
1579  m->setSizeMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "size_map_unit_scale" )] ) );
1580  if ( props.contains( QStringLiteral( "horizontal_anchor_point" ) ) )
1581  {
1582  m->setHorizontalAnchorPoint( QgsMarkerSymbolLayer::HorizontalAnchorPoint( props[ QStringLiteral( "horizontal_anchor_point" )].toInt() ) );
1583  }
1584  if ( props.contains( QStringLiteral( "vertical_anchor_point" ) ) )
1585  {
1586  m->setVerticalAnchorPoint( QgsMarkerSymbolLayer::VerticalAnchorPoint( props[ QStringLiteral( "vertical_anchor_point" )].toInt() ) );
1587  }
1588 
1590 
1591  m->restoreOldDataDefinedProperties( props );
1592 
1593  return m;
1594 }
1595 
1597 {
1598  return QStringLiteral( "FilledMarker" );
1599 }
1600 
1602 {
1603  if ( mFill )
1604  {
1605  mFill->startRender( context.renderContext(), context.fields() );
1606  }
1607 
1609 }
1610 
1612 {
1613  if ( mFill )
1614  {
1615  mFill->stopRender( context.renderContext() );
1616  }
1617 }
1618 
1620 {
1621  QgsStringMap map;
1622  map[QStringLiteral( "name" )] = encodeShape( mShape );
1623  map[QStringLiteral( "size" )] = QString::number( mSize );
1624  map[QStringLiteral( "size_unit" )] = QgsUnitTypes::encodeUnit( mSizeUnit );
1625  map[QStringLiteral( "size_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mSizeMapUnitScale );
1626  map[QStringLiteral( "angle" )] = QString::number( mAngle );
1627  map[QStringLiteral( "offset" )] = QgsSymbolLayerUtils::encodePoint( mOffset );
1628  map[QStringLiteral( "offset_unit" )] = QgsUnitTypes::encodeUnit( mOffsetUnit );
1629  map[QStringLiteral( "offset_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mOffsetMapUnitScale );
1630  map[QStringLiteral( "scale_method" )] = QgsSymbolLayerUtils::encodeScaleMethod( mScaleMethod );
1631  map[QStringLiteral( "horizontal_anchor_point" )] = QString::number( mHorizontalAnchorPoint );
1632  map[QStringLiteral( "vertical_anchor_point" )] = QString::number( mVerticalAnchorPoint );
1633 
1634  if ( mFill )
1635  {
1636  map[QStringLiteral( "color" )] = QgsSymbolLayerUtils::encodeColor( mFill->color() );
1637  }
1638  return map;
1639 }
1640 
1642 {
1644  copyPaintEffect( m );
1646  m->setSubSymbol( mFill->clone() );
1647  return m;
1648 }
1649 
1651 {
1652  return mFill.get();
1653 }
1654 
1656 {
1657  if ( symbol && symbol->type() == QgsSymbol::Fill )
1658  {
1659  mFill.reset( static_cast<QgsFillSymbol *>( symbol ) );
1660  return true;
1661  }
1662  else
1663  {
1664  delete symbol;
1665  return false;
1666  }
1667 }
1668 
1670 {
1671  if ( mFill )
1672  {
1673  return QgsSymbolLayerUtils::estimateMaxSymbolBleed( mFill.get(), context );
1674  }
1675  return 0;
1676 }
1677 
1679 {
1680  QSet<QString> attr = QgsSimpleMarkerSymbolLayerBase::usedAttributes( context );
1681  if ( mFill )
1682  attr.unite( mFill->usedAttributes( context ) );
1683  return attr;
1684 }
1685 
1687 {
1689  return true;
1690  if ( mFill && mFill->hasDataDefinedProperties() )
1691  return true;
1692  return false;
1693 }
1694 
1696 {
1697  mColor = c;
1698  if ( mFill )
1699  mFill->setColor( c );
1700 }
1701 
1703 {
1704  return mFill ? mFill->color() : mColor;
1705 }
1706 
1707 void QgsFilledMarkerSymbolLayer::draw( QgsSymbolRenderContext &context, QgsSimpleMarkerSymbolLayerBase::Shape shape, const QPolygonF &polygon, const QPainterPath &path )
1708 {
1709  //making changes here? Don't forget to also update ::bounds if the changes affect the bounding box
1710  //of the rendered point!
1711 
1712  QPainter *p = context.renderContext().painter();
1713  if ( !p )
1714  {
1715  return;
1716  }
1717 
1718  if ( shapeIsFilled( shape ) )
1719  {
1720  p->setBrush( Qt::red );
1721  }
1722  else
1723  {
1724  p->setBrush( Qt::NoBrush );
1725  }
1726  p->setPen( Qt::black );
1727 
1728  if ( !polygon.isEmpty() )
1729  {
1730  mFill->renderPolygon( polygon, /* rings */ nullptr, context.feature(), context.renderContext(), -1, context.selected() );
1731  }
1732  else
1733  {
1734  QPolygonF poly = path.toFillPolygon();
1735  mFill->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext(), -1, context.selected() );
1736  }
1737 
1738 
1739 }
1740 
1741 
1743 
1744 
1745 QgsSvgMarkerSymbolLayer::QgsSvgMarkerSymbolLayer( const QString &path, double size, double angle, QgsSymbol::ScaleMethod scaleMethod )
1746 {
1747  mPath = path;
1748  mSize = size;
1749  mAngle = angle;
1750  mOffset = QPointF( 0, 0 );
1752  mStrokeWidth = 0.2;
1754  mColor = QColor( 35, 35, 35 );
1755  mStrokeColor = QColor( 35, 35, 35 );
1757 }
1758 
1759 
1761 {
1762  QString name;
1763  double size = DEFAULT_SVGMARKER_SIZE;
1764  double angle = DEFAULT_SVGMARKER_ANGLE;
1766 
1767  if ( props.contains( QStringLiteral( "name" ) ) )
1768  name = props[QStringLiteral( "name" )];
1769  if ( props.contains( QStringLiteral( "size" ) ) )
1770  size = props[QStringLiteral( "size" )].toDouble();
1771  if ( props.contains( QStringLiteral( "angle" ) ) )
1772  angle = props[QStringLiteral( "angle" )].toDouble();
1773  if ( props.contains( QStringLiteral( "scale_method" ) ) )
1774  scaleMethod = QgsSymbolLayerUtils::decodeScaleMethod( props[QStringLiteral( "scale_method" )] );
1775 
1777 
1778  //we only check the svg default parameters if necessary, since it could be expensive
1779  if ( !props.contains( QStringLiteral( "fill" ) ) && !props.contains( QStringLiteral( "color" ) ) && !props.contains( QStringLiteral( "outline" ) ) &&
1780  !props.contains( QStringLiteral( "outline_color" ) ) && !props.contains( QStringLiteral( "outline-width" ) ) && !props.contains( QStringLiteral( "outline_width" ) ) )
1781  {
1782  QColor fillColor, strokeColor;
1783  double fillOpacity = 1.0;
1784  double strokeOpacity = 1.0;
1785  double strokeWidth;
1786  bool hasFillParam = false, hasFillOpacityParam = false, hasStrokeParam = false, hasStrokeWidthParam = false, hasStrokeOpacityParam = false;
1787  bool hasDefaultFillColor = false, hasDefaultFillOpacity = false, hasDefaultStrokeColor = false, hasDefaultStrokeWidth = false, hasDefaultStrokeOpacity = false;
1788  QgsApplication::svgCache()->containsParams( name, hasFillParam, hasDefaultFillColor, fillColor,
1789  hasFillOpacityParam, hasDefaultFillOpacity, fillOpacity,
1790  hasStrokeParam, hasDefaultStrokeColor, strokeColor,
1791  hasStrokeWidthParam, hasDefaultStrokeWidth, strokeWidth,
1792  hasStrokeOpacityParam, hasDefaultStrokeOpacity, strokeOpacity );
1793  if ( hasDefaultFillColor )
1794  {
1795  m->setFillColor( fillColor );
1796  }
1797  if ( hasDefaultFillOpacity )
1798  {
1799  QColor c = m->fillColor();
1800  c.setAlphaF( fillOpacity );
1801  m->setFillColor( c );
1802  }
1803  if ( hasDefaultStrokeColor )
1804  {
1806  }
1807  if ( hasDefaultStrokeWidth )
1808  {
1810  }
1811  if ( hasDefaultStrokeOpacity )
1812  {
1813  QColor c = m->strokeColor();
1814  c.setAlphaF( strokeOpacity );
1815  m->setStrokeColor( c );
1816  }
1817  }
1818 
1819  if ( props.contains( QStringLiteral( "size_unit" ) ) )
1820  m->setSizeUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "size_unit" )] ) );
1821  if ( props.contains( QStringLiteral( "size_map_unit_scale" ) ) )
1822  m->setSizeMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "size_map_unit_scale" )] ) );
1823  if ( props.contains( QStringLiteral( "fixedAspectRatio" ) ) )
1824  m->setFixedAspectRatio( props[QStringLiteral( "fixedAspectRatio" )].toDouble() );
1825  if ( props.contains( QStringLiteral( "offset" ) ) )
1826  m->setOffset( QgsSymbolLayerUtils::decodePoint( props[QStringLiteral( "offset" )] ) );
1827  if ( props.contains( QStringLiteral( "offset_unit" ) ) )
1828  m->setOffsetUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "offset_unit" )] ) );
1829  if ( props.contains( QStringLiteral( "offset_map_unit_scale" ) ) )
1830  m->setOffsetMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "offset_map_unit_scale" )] ) );
1831  if ( props.contains( QStringLiteral( "fill" ) ) )
1832  {
1833  //pre 2.5 projects used "fill"
1834  m->setFillColor( QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "fill" )] ) );
1835  }
1836  else if ( props.contains( QStringLiteral( "color" ) ) )
1837  {
1838  m->setFillColor( QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "color" )] ) );
1839  }
1840  if ( props.contains( QStringLiteral( "outline" ) ) )
1841  {
1842  //pre 2.5 projects used "outline"
1843  m->setStrokeColor( QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "outline" )] ) );
1844  }
1845  else if ( props.contains( QStringLiteral( "outline_color" ) ) )
1846  {
1847  m->setStrokeColor( QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "outline_color" )] ) );
1848  }
1849  else if ( props.contains( QStringLiteral( "line_color" ) ) )
1850  {
1851  m->setStrokeColor( QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "line_color" )] ) );
1852  }
1853 
1854  if ( props.contains( QStringLiteral( "outline-width" ) ) )
1855  {
1856  //pre 2.5 projects used "outline-width"
1857  m->setStrokeWidth( props[QStringLiteral( "outline-width" )].toDouble() );
1858  }
1859  else if ( props.contains( QStringLiteral( "outline_width" ) ) )
1860  {
1861  m->setStrokeWidth( props[QStringLiteral( "outline_width" )].toDouble() );
1862  }
1863  else if ( props.contains( QStringLiteral( "line_width" ) ) )
1864  {
1865  m->setStrokeWidth( props[QStringLiteral( "line_width" )].toDouble() );
1866  }
1867 
1868  if ( props.contains( QStringLiteral( "outline_width_unit" ) ) )
1869  {
1870  m->setStrokeWidthUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "outline_width_unit" )] ) );
1871  }
1872  else if ( props.contains( QStringLiteral( "line_width_unit" ) ) )
1873  {
1874  m->setStrokeWidthUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "line_width_unit" )] ) );
1875  }
1876  if ( props.contains( QStringLiteral( "outline_width_map_unit_scale" ) ) )
1877  m->setStrokeWidthMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "outline_width_map_unit_scale" )] ) );
1878 
1879  if ( props.contains( QStringLiteral( "horizontal_anchor_point" ) ) )
1880  {
1881  m->setHorizontalAnchorPoint( QgsMarkerSymbolLayer::HorizontalAnchorPoint( props[ QStringLiteral( "horizontal_anchor_point" )].toInt() ) );
1882  }
1883  if ( props.contains( QStringLiteral( "vertical_anchor_point" ) ) )
1884  {
1885  m->setVerticalAnchorPoint( QgsMarkerSymbolLayer::VerticalAnchorPoint( props[ QStringLiteral( "vertical_anchor_point" )].toInt() ) );
1886  }
1887 
1888  m->restoreOldDataDefinedProperties( props );
1889 
1891 
1892  return m;
1893 }
1894 
1895 void QgsSvgMarkerSymbolLayer::resolvePaths( QgsStringMap &properties, const QgsPathResolver &pathResolver, bool saving )
1896 {
1897  QgsStringMap::iterator it = properties.find( QStringLiteral( "name" ) );
1898  if ( it != properties.end() )
1899  {
1900  if ( saving )
1901  it.value() = QgsSymbolLayerUtils::svgSymbolPathToName( it.value(), pathResolver );
1902  else
1903  it.value() = QgsSymbolLayerUtils::svgSymbolNameToPath( it.value(), pathResolver );
1904  }
1905 }
1906 
1907 void QgsSvgMarkerSymbolLayer::setPath( const QString &path )
1908 {
1909  mPath = path;
1910  QColor defaultFillColor, defaultStrokeColor;
1911  double strokeWidth, fillOpacity, strokeOpacity;
1912  bool hasFillParam = false, hasFillOpacityParam = false, hasStrokeParam = false, hasStrokeWidthParam = false, hasStrokeOpacityParam = false;
1913  bool hasDefaultFillColor = false, hasDefaultFillOpacity = false, hasDefaultStrokeColor = false, hasDefaultStrokeWidth = false, hasDefaultStrokeOpacity = false;
1914  QgsApplication::svgCache()->containsParams( path, hasFillParam, hasDefaultFillColor, defaultFillColor,
1915  hasFillOpacityParam, hasDefaultFillOpacity, fillOpacity,
1916  hasStrokeParam, hasDefaultStrokeColor, defaultStrokeColor,
1917  hasStrokeWidthParam, hasDefaultStrokeWidth, strokeWidth,
1918  hasStrokeOpacityParam, hasDefaultStrokeOpacity, strokeOpacity );
1919 
1920  double newFillOpacity = hasFillOpacityParam ? fillColor().alphaF() : 1.0;
1921  double newStrokeOpacity = hasStrokeOpacityParam ? strokeColor().alphaF() : 1.0;
1922 
1923  if ( hasDefaultFillColor )
1924  {
1925  defaultFillColor.setAlphaF( newFillOpacity );
1926  setFillColor( defaultFillColor );
1927  }
1928  if ( hasDefaultFillOpacity )
1929  {
1930  QColor c = fillColor();
1931  c.setAlphaF( fillOpacity );
1932  setFillColor( c );
1933  }
1934  if ( hasDefaultStrokeColor )
1935  {
1936  defaultStrokeColor.setAlphaF( newStrokeOpacity );
1937  setStrokeColor( defaultStrokeColor );
1938  }
1939  if ( hasDefaultStrokeWidth )
1940  {
1942  }
1943  if ( hasDefaultStrokeOpacity )
1944  {
1945  QColor c = strokeColor();
1946  c.setAlphaF( strokeOpacity );
1947  setStrokeColor( c );
1948  }
1949 
1951 }
1952 
1954 {
1955  if ( mDefaultAspectRatio == 0.0 )
1956  {
1957  //size
1958  double size = mSize;
1959  //assume 88 dpi as standard value
1960  double widthScaleFactor = 3.465;
1961  QSizeF svgViewbox = QgsApplication::svgCache()->svgViewboxSize( mPath, size, mColor, mStrokeColor, mStrokeWidth, widthScaleFactor );
1962  // set default aspect ratio
1963  mDefaultAspectRatio = svgViewbox.isValid() ? svgViewbox.height() / svgViewbox.width() : 0.0;
1964  }
1965  return mDefaultAspectRatio;
1966 }
1967 
1969 {
1970  bool aPreservedAspectRatio = preservedAspectRatio();
1971  if ( aPreservedAspectRatio && !par )
1972  {
1974  }
1975  else if ( !aPreservedAspectRatio && par )
1976  {
1977  mFixedAspectRatio = 0.0;
1978  }
1979  return preservedAspectRatio();
1980 }
1981 
1982 
1984 {
1985  return QStringLiteral( "SvgMarker" );
1986 }
1987 
1989 {
1990  QgsMarkerSymbolLayer::startRender( context ); // get anchor point expressions
1991  Q_UNUSED( context )
1992 }
1993 
1995 {
1996  Q_UNUSED( context )
1997 }
1998 
2000 {
2001  QPainter *p = context.renderContext().painter();
2002  if ( !p )
2003  return;
2004 
2005  bool hasDataDefinedSize = false;
2006  double scaledSize = calculateSize( context, hasDataDefinedSize );
2007  double size = context.renderContext().convertToPainterUnits( scaledSize, mSizeUnit, mSizeMapUnitScale );
2008 
2009  //don't render symbols with size below one or above 10,000 pixels
2010  if ( static_cast< int >( size ) < 1 || 10000.0 < size )
2011  {
2012  return;
2013  }
2014 
2015  p->save();
2016 
2017  bool hasDataDefinedAspectRatio = false;
2018  double aspectRatio = calculateAspectRatio( context, scaledSize, hasDataDefinedAspectRatio );
2019 
2020  QPointF outputOffset;
2021  double angle = 0.0;
2022  calculateOffsetAndRotation( context, scaledSize, outputOffset, angle );
2023 
2024  p->translate( point + outputOffset );
2025 
2026  bool rotated = !qgsDoubleNear( angle, 0 );
2027  if ( rotated )
2028  p->rotate( angle );
2029 
2030  QString path = mPath;
2032  {
2033  context.setOriginalValueVariable( mPath );
2035  context.renderContext().pathResolver() );
2036  }
2037 
2038  double strokeWidth = mStrokeWidth;
2040  {
2043  }
2045 
2046  QColor fillColor = mColor;
2048  {
2051  }
2052 
2053  QColor strokeColor = mStrokeColor;
2055  {
2058  }
2059 
2060  bool fitsInCache = true;
2061  bool usePict = true;
2062  double hwRatio = 1.0;
2063  if ( !context.renderContext().forceVectorOutput() && !rotated )
2064  {
2066  context.renderContext().scaleFactor(), fitsInCache, aspectRatio,
2068  if ( fitsInCache && img.width() > 1 )
2069  {
2070  usePict = false;
2071  //consider transparency
2072  if ( !qgsDoubleNear( context.opacity(), 1.0 ) )
2073  {
2074  QImage transparentImage = img.copy();
2075  QgsSymbolLayerUtils::multiplyImageOpacity( &transparentImage, context.opacity() );
2076  p->drawImage( -transparentImage.width() / 2.0, -transparentImage.height() / 2.0, transparentImage );
2077  hwRatio = static_cast< double >( transparentImage.height() ) / static_cast< double >( transparentImage.width() );
2078  }
2079  else
2080  {
2081  p->drawImage( -img.width() / 2.0, -img.height() / 2.0, img );
2082  hwRatio = static_cast< double >( img.height() ) / static_cast< double >( img.width() );
2083  }
2084  }
2085  }
2086 
2087  if ( usePict || !fitsInCache )
2088  {
2089  p->setOpacity( context.opacity() );
2091  context.renderContext().scaleFactor(), context.renderContext().forceVectorOutput(), aspectRatio,
2093  if ( pct.width() > 1 )
2094  {
2095  p->save();
2096  _fixQPictureDPI( p );
2097  p->drawPicture( 0, 0, pct );
2098  p->restore();
2099  hwRatio = static_cast< double >( pct.height() ) / static_cast< double >( pct.width() );
2100  }
2101  }
2102 
2103  if ( context.selected() )
2104  {
2105  QPen pen( context.renderContext().selectionColor() );
2106  double penWidth = context.renderContext().convertToPainterUnits( 1, QgsUnitTypes::RenderMillimeters );
2107  if ( penWidth > size / 20 )
2108  {
2109  // keep the pen width from covering symbol
2110  penWidth = size / 20;
2111  }
2112  double penOffset = penWidth / 2;
2113  pen.setWidth( penWidth );
2114  p->setPen( pen );
2115  p->setBrush( Qt::NoBrush );
2116  double wSize = size + penOffset;
2117  double hSize = size * hwRatio + penOffset;
2118  p->drawRect( QRectF( -wSize / 2.0, -hSize / 2.0, wSize, hSize ) );
2119  }
2120 
2121  p->restore();
2122 
2124  {
2125  // workaround issue with nested QPictures forgetting antialiasing flag - see https://github.com/qgis/QGIS/issues/22909
2126  p->setRenderHint( QPainter::Antialiasing );
2127  }
2128 
2129 }
2130 
2131 double QgsSvgMarkerSymbolLayer::calculateSize( QgsSymbolRenderContext &context, bool &hasDataDefinedSize ) const
2132 {
2133  double scaledSize = mSize;
2135 
2136  bool ok = true;
2137  if ( hasDataDefinedSize )
2138  {
2139  context.setOriginalValueVariable( mSize );
2141  }
2142  else
2143  {
2145  if ( hasDataDefinedSize )
2146  {
2147  context.setOriginalValueVariable( mSize );
2149  }
2150  }
2151 
2152  if ( hasDataDefinedSize && ok )
2153  {
2154  switch ( mScaleMethod )
2155  {
2156  case QgsSymbol::ScaleArea:
2157  scaledSize = std::sqrt( scaledSize );
2158  break;
2160  break;
2161  }
2162  }
2163 
2164  return scaledSize;
2165 }
2166 
2167 double QgsSvgMarkerSymbolLayer::calculateAspectRatio( QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedAspectRatio ) const
2168 {
2170  if ( !hasDataDefinedAspectRatio )
2171  return mFixedAspectRatio;
2172 
2174  return 0.0;
2175 
2176  double scaledAspectRatio = mDefaultAspectRatio;
2177  if ( mFixedAspectRatio > 0.0 )
2178  scaledAspectRatio = mFixedAspectRatio;
2179 
2180  double defaultHeight = mSize * scaledAspectRatio;
2181  scaledAspectRatio = defaultHeight / scaledSize;
2182 
2183  bool ok = true;
2184  double scaledHeight = scaledSize * scaledAspectRatio;
2186  {
2187  context.setOriginalValueVariable( defaultHeight );
2188  scaledHeight = mDataDefinedProperties.valueAsDouble( QgsSymbolLayer::PropertyHeight, context.renderContext().expressionContext(), defaultHeight, &ok );
2189  }
2190 
2191  if ( hasDataDefinedAspectRatio && ok )
2192  {
2193  switch ( mScaleMethod )
2194  {
2195  case QgsSymbol::ScaleArea:
2196  scaledHeight = sqrt( scaledHeight );
2197  break;
2199  break;
2200  }
2201  }
2202 
2203  scaledAspectRatio = scaledHeight / scaledSize;
2204 
2205  return scaledAspectRatio;
2206 }
2207 
2208 void QgsSvgMarkerSymbolLayer::calculateOffsetAndRotation( QgsSymbolRenderContext &context, double scaledSize, QPointF &offset, double &angle ) const
2209 {
2210  //offset
2211  double offsetX = 0;
2212  double offsetY = 0;
2213  markerOffset( context, scaledSize, scaledSize, offsetX, offsetY );
2214  offset = QPointF( offsetX, offsetY );
2215 
2216  angle = mAngle + mLineAngle;
2218  {
2219  context.setOriginalValueVariable( mAngle );
2221  }
2222 
2224  if ( hasDataDefinedRotation )
2225  {
2226  // For non-point markers, "dataDefinedRotation" means following the
2227  // shape (shape-data defined). For them, "field-data defined" does
2228  // not work at all. TODO: if "field-data defined" ever gets implemented
2229  // we'll need a way to distinguish here between the two, possibly
2230  // using another flag in renderHints()
2231  const QgsFeature *f = context.feature();
2232  if ( f )
2233  {
2234  if ( f->hasGeometry() && f->geometry().type() == QgsWkbTypes::PointGeometry )
2235  {
2236  const QgsMapToPixel &m2p = context.renderContext().mapToPixel();
2237  angle += m2p.mapRotation();
2238  }
2239  }
2240  }
2241 
2242  if ( angle )
2244 }
2245 
2246 
2248 {
2249  QgsStringMap map;
2250  map[QStringLiteral( "name" )] = mPath;
2251  map[QStringLiteral( "size" )] = QString::number( mSize );
2252  map[QStringLiteral( "size_unit" )] = QgsUnitTypes::encodeUnit( mSizeUnit );
2253  map[QStringLiteral( "size_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mSizeMapUnitScale );
2254  map[QStringLiteral( "fixedAspectRatio" )] = QString::number( mFixedAspectRatio );
2255  map[QStringLiteral( "angle" )] = QString::number( mAngle );
2256  map[QStringLiteral( "offset" )] = QgsSymbolLayerUtils::encodePoint( mOffset );
2257  map[QStringLiteral( "offset_unit" )] = QgsUnitTypes::encodeUnit( mOffsetUnit );
2258  map[QStringLiteral( "offset_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mOffsetMapUnitScale );
2259  map[QStringLiteral( "scale_method" )] = QgsSymbolLayerUtils::encodeScaleMethod( mScaleMethod );
2260  map[QStringLiteral( "color" )] = QgsSymbolLayerUtils::encodeColor( mColor );
2261  map[QStringLiteral( "outline_color" )] = QgsSymbolLayerUtils::encodeColor( mStrokeColor );
2262  map[QStringLiteral( "outline_width" )] = QString::number( mStrokeWidth );
2263  map[QStringLiteral( "outline_width_unit" )] = QgsUnitTypes::encodeUnit( mStrokeWidthUnit );
2264  map[QStringLiteral( "outline_width_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mStrokeWidthMapUnitScale );
2265  map[QStringLiteral( "horizontal_anchor_point" )] = QString::number( mHorizontalAnchorPoint );
2266  map[QStringLiteral( "vertical_anchor_point" )] = QString::number( mVerticalAnchorPoint );
2267  return map;
2268 }
2269 
2271 {
2274  m->setColor( mColor );
2279  m->setOffset( mOffset );
2280  m->setOffsetUnit( mOffsetUnit );
2282  m->setSizeUnit( mSizeUnit );
2287  copyPaintEffect( m );
2288  return m;
2289 }
2290 
2292 {
2294  mStrokeWidthUnit = unit;
2295 }
2296 
2298 {
2300  if ( unit != mStrokeWidthUnit )
2301  {
2303  }
2304  return unit;
2305 }
2306 
2308 {
2310  mStrokeWidthMapUnitScale = scale;
2311 }
2312 
2314 {
2316  {
2317  return mStrokeWidthMapUnitScale;
2318  }
2319  return QgsMapUnitScale();
2320 }
2321 
2322 void QgsSvgMarkerSymbolLayer::writeSldMarker( QDomDocument &doc, QDomElement &element, const QgsStringMap &props ) const
2323 {
2324  // <Graphic>
2325  QDomElement graphicElem = doc.createElement( QStringLiteral( "se:Graphic" ) );
2326  element.appendChild( graphicElem );
2327 
2328  // encode a parametric SVG reference
2332 
2333  // <Rotation>
2334  QString angleFunc;
2335  bool ok;
2336  double angle = props.value( QStringLiteral( "angle" ), QStringLiteral( "0" ) ).toDouble( &ok );
2337  if ( !ok )
2338  {
2339  angleFunc = QStringLiteral( "%1 + %2" ).arg( props.value( QStringLiteral( "angle" ), QStringLiteral( "0" ) ) ).arg( mAngle );
2340  }
2341  else if ( !qgsDoubleNear( angle + mAngle, 0.0 ) )
2342  {
2343  angleFunc = QString::number( angle + mAngle );
2344  }
2345 
2346  QgsSymbolLayerUtils::createRotationElement( doc, graphicElem, angleFunc );
2347 
2348  // <Displacement>
2351 }
2352 
2354 {
2355  QgsDebugMsgLevel( QStringLiteral( "Entered." ), 4 );
2356 
2357  QDomElement graphicElem = element.firstChildElement( QStringLiteral( "Graphic" ) );
2358  if ( graphicElem.isNull() )
2359  return nullptr;
2360 
2361  QString path, mimeType;
2362  QColor fillColor;
2363  double size;
2364 
2365  if ( !QgsSymbolLayerUtils::externalGraphicFromSld( graphicElem, path, mimeType, fillColor, size ) )
2366  return nullptr;
2367 
2368  QString uom = element.attribute( QStringLiteral( "uom" ) );
2370 
2371  if ( mimeType != QLatin1String( "image/svg+xml" ) )
2372  return nullptr;
2373 
2374  double angle = 0.0;
2375  QString angleFunc;
2376  if ( QgsSymbolLayerUtils::rotationFromSldElement( graphicElem, angleFunc ) )
2377  {
2378  bool ok;
2379  double d = angleFunc.toDouble( &ok );
2380  if ( ok )
2381  angle = d;
2382  }
2383 
2384  QPointF offset;
2386 
2388  m->setOutputUnit( QgsUnitTypes::RenderUnit::RenderPixels );
2389  m->setFillColor( fillColor );
2390  //m->setStrokeColor( strokeColor );
2391  //m->setStrokeWidth( strokeWidth );
2392  m->setAngle( angle );
2393  m->setOffset( offset );
2394  return m;
2395 }
2396 
2397 bool QgsSvgMarkerSymbolLayer::writeDxf( QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, QgsSymbolRenderContext &context, QPointF shift ) const
2398 {
2399  //size
2400  double size = mSize;
2401 
2402  bool hasDataDefinedSize = mDataDefinedProperties.isActive( QgsSymbolLayer::PropertySize );
2403 
2404  bool ok = true;
2405  if ( hasDataDefinedSize )
2406  {
2407  context.setOriginalValueVariable( mSize );
2409  }
2410 
2411  if ( hasDataDefinedSize && ok )
2412  {
2413  switch ( mScaleMethod )
2414  {
2415  case QgsSymbol::ScaleArea:
2416  size = std::sqrt( size );
2417  break;
2419  break;
2420  }
2421  }
2422 
2424  {
2425  size *= mmMapUnitScaleFactor;
2426  }
2427 
2428  //offset, angle
2429  QPointF offset = mOffset;
2430 
2432  {
2434  const QVariant val = mDataDefinedProperties.value( QgsSymbolLayer::PropertyOffset, context.renderContext().expressionContext(), QString() );
2435  const QPointF res = QgsSymbolLayerUtils::toPoint( val, &ok );
2436  if ( ok )
2437  offset = res;
2438  }
2439  double offsetX = offset.x();
2440  double offsetY = offset.y();
2441 
2442  QPointF outputOffset( offsetX, offsetY );
2443 
2444  double angle = mAngle + mLineAngle;
2446  {
2447  context.setOriginalValueVariable( mAngle );
2449  }
2450 
2451  if ( angle )
2452  outputOffset = _rotatedOffset( outputOffset, angle );
2453 
2454  outputOffset *= e.mapUnitScaleFactor( e.symbologyScale(), mOffsetUnit, e.mapUnits(), context.renderContext().mapToPixel().mapUnitsPerPixel() );
2455 
2456  QString path = mPath;
2458  {
2459  context.setOriginalValueVariable( mPath );
2461  context.renderContext().pathResolver() );
2462  }
2463 
2464  double strokeWidth = mStrokeWidth;
2466  {
2469  }
2471 
2472  QColor fillColor = mColor;
2474  {
2477  }
2478 
2479  QColor strokeColor = mStrokeColor;
2481  {
2484  }
2485 
2486  const QByteArray &svgContent = QgsApplication::svgCache()->svgContent( path, size, fillColor, strokeColor, strokeWidth,
2489 
2490  QSvgRenderer r( svgContent );
2491  if ( !r.isValid() )
2492  return false;
2493 
2494  QgsDxfPaintDevice pd( &e );
2495  pd.setDrawingSize( QSizeF( r.defaultSize() ) );
2496 
2497  QSizeF outSize( r.defaultSize() );
2498  outSize.scale( size, size, Qt::KeepAspectRatio );
2499 
2500  QPainter p;
2501  p.begin( &pd );
2502  if ( !qgsDoubleNear( angle, 0.0 ) )
2503  {
2504  p.translate( r.defaultSize().width() / 2.0, r.defaultSize().height() / 2.0 );
2505  p.rotate( angle );
2506  p.translate( -r.defaultSize().width() / 2.0, -r.defaultSize().height() / 2.0 );
2507  }
2508  pd.setShift( shift + QPointF( outputOffset.x(), -outputOffset.y() ) );
2509  pd.setOutputSize( QRectF( -outSize.width() / 2.0, -outSize.height() / 2.0, outSize.width(), outSize.height() ) );
2510  pd.setLayer( layerName );
2511  r.render( &p );
2512  p.end();
2513  return true;
2514 }
2515 
2517 {
2518  bool hasDataDefinedSize = false;
2519  double scaledSize = calculateSize( context, hasDataDefinedSize );
2520  scaledSize = context.renderContext().convertToPainterUnits( scaledSize, mSizeUnit, mSizeMapUnitScale );
2521 
2522  //don't render symbols with size below one or above 10,000 pixels
2523  if ( static_cast< int >( scaledSize ) < 1 || 10000.0 < scaledSize )
2524  {
2525  return QRectF();
2526  }
2527 
2528  QPointF outputOffset;
2529  double angle = 0.0;
2530  calculateOffsetAndRotation( context, scaledSize, outputOffset, angle );
2531 
2532  QString path = mPath;
2534  {
2535  context.setOriginalValueVariable( mPath );
2537  context.renderContext().pathResolver() );
2538  }
2539 
2540  double strokeWidth = mStrokeWidth;
2542  {
2545  }
2547 
2548  //need to get colors to take advantage of cached SVGs
2549  QColor fillColor = mColor;
2551  {
2554  }
2555 
2556  QColor strokeColor = mStrokeColor;
2558  {
2561  }
2562 
2563  QSizeF svgViewbox = QgsApplication::svgCache()->svgViewboxSize( path, scaledSize, fillColor, strokeColor, strokeWidth,
2566 
2567  double scaledHeight = svgViewbox.isValid() ? scaledSize * svgViewbox.height() / svgViewbox.width() : scaledSize;
2568 
2569  QMatrix transform;
2570 
2571  // move to the desired position
2572  transform.translate( point.x() + outputOffset.x(), point.y() + outputOffset.y() );
2573 
2574  if ( !qgsDoubleNear( angle, 0.0 ) )
2575  transform.rotate( angle );
2576 
2577  //antialiasing
2578  strokeWidth += 1.0 / 2.0;
2579 
2580  QRectF symbolBounds = transform.mapRect( QRectF( -scaledSize / 2.0,
2581  -scaledHeight / 2.0,
2582  scaledSize,
2583  scaledHeight ) );
2584 
2585  //extend bounds by pen width / 2.0
2586  symbolBounds.adjust( -strokeWidth / 2.0, -strokeWidth / 2.0,
2587  strokeWidth / 2.0, strokeWidth / 2.0 );
2588 
2589  return symbolBounds;
2590 
2591 }
2592 
2594 
2595 QgsRasterMarkerSymbolLayer::QgsRasterMarkerSymbolLayer( const QString &path, double size, double angle, QgsSymbol::ScaleMethod scaleMethod )
2596  : mPath( path )
2597 {
2598  mSize = size;
2599  mAngle = angle;
2600  mOffset = QPointF( 0, 0 );
2603 }
2604 
2605 
2607 {
2608  QString path;
2612 
2613  if ( props.contains( QStringLiteral( "imageFile" ) ) )
2614  path = props[QStringLiteral( "imageFile" )];
2615  if ( props.contains( QStringLiteral( "size" ) ) )
2616  size = props[QStringLiteral( "size" )].toDouble();
2617  if ( props.contains( QStringLiteral( "angle" ) ) )
2618  angle = props[QStringLiteral( "angle" )].toDouble();
2619  if ( props.contains( QStringLiteral( "scale_method" ) ) )
2620  scaleMethod = QgsSymbolLayerUtils::decodeScaleMethod( props[QStringLiteral( "scale_method" )] );
2621 
2623 
2624  if ( props.contains( QStringLiteral( "alpha" ) ) )
2625  {
2626  m->setOpacity( props[QStringLiteral( "alpha" )].toDouble() );
2627  }
2628 
2629  if ( props.contains( QStringLiteral( "size_unit" ) ) )
2630  m->setSizeUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "size_unit" )] ) );
2631  if ( props.contains( QStringLiteral( "size_map_unit_scale" ) ) )
2632  m->setSizeMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "size_map_unit_scale" )] ) );
2633  if ( props.contains( QStringLiteral( "fixedAspectRatio" ) ) )
2634  m->setFixedAspectRatio( props[QStringLiteral( "fixedAspectRatio" )].toDouble() );
2635 
2636  if ( props.contains( QStringLiteral( "offset" ) ) )
2637  m->setOffset( QgsSymbolLayerUtils::decodePoint( props[QStringLiteral( "offset" )] ) );
2638  if ( props.contains( QStringLiteral( "offset_unit" ) ) )
2639  m->setOffsetUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "offset_unit" )] ) );
2640  if ( props.contains( QStringLiteral( "offset_map_unit_scale" ) ) )
2641  m->setOffsetMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "offset_map_unit_scale" )] ) );
2642 
2643  if ( props.contains( QStringLiteral( "horizontal_anchor_point" ) ) )
2644  {
2645  m->setHorizontalAnchorPoint( QgsMarkerSymbolLayer::HorizontalAnchorPoint( props[ QStringLiteral( "horizontal_anchor_point" )].toInt() ) );
2646  }
2647  if ( props.contains( QStringLiteral( "vertical_anchor_point" ) ) )
2648  {
2649  m->setVerticalAnchorPoint( QgsMarkerSymbolLayer::VerticalAnchorPoint( props[ QStringLiteral( "vertical_anchor_point" )].toInt() ) );
2650  }
2651 
2652  m->restoreOldDataDefinedProperties( props );
2654 
2655  return m;
2656 }
2657 
2658 void QgsRasterMarkerSymbolLayer::resolvePaths( QgsStringMap &properties, const QgsPathResolver &pathResolver, bool saving )
2659 {
2660  QgsStringMap::iterator it = properties.find( QStringLiteral( "name" ) );
2661  if ( it != properties.end() )
2662  {
2663  if ( saving )
2664  it.value() = QgsSymbolLayerUtils::svgSymbolPathToName( it.value(), pathResolver );
2665  else
2666  it.value() = QgsSymbolLayerUtils::svgSymbolNameToPath( it.value(), pathResolver );
2667  }
2668 }
2669 
2670 void QgsRasterMarkerSymbolLayer::setPath( const QString &path )
2671 {
2672  mPath = path;
2674 }
2675 
2677 {
2678  bool aPreservedAspectRatio = preservedAspectRatio();
2679  if ( aPreservedAspectRatio && !par )
2680  {
2682  }
2683  else if ( !aPreservedAspectRatio && par )
2684  {
2685  mFixedAspectRatio = 0.0;
2686  }
2687  return preservedAspectRatio();
2688 }
2689 
2691 {
2692  if ( mDefaultAspectRatio == 0.0 )
2693  {
2695  mDefaultAspectRatio = ( !size.isNull() && size.isValid() && size.width() > 0 ) ? static_cast< double >( size.height() ) / static_cast< double >( size.width() ) : 0.0;
2696  }
2697  return mDefaultAspectRatio;
2698 }
2699 
2701 {
2702  return QStringLiteral( "RasterMarker" );
2703 }
2704 
2706 {
2707  QPainter *p = context.renderContext().painter();
2708  if ( !p )
2709  return;
2710 
2711  QString path = mPath;
2713  {
2714  context.setOriginalValueVariable( mPath );
2716  }
2717 
2718  if ( path.isEmpty() )
2719  return;
2720 
2721  double width = 0.0;
2722  double height = 0.0;
2723 
2724  bool hasDataDefinedSize = false;
2725  double scaledSize = calculateSize( context, hasDataDefinedSize );
2726 
2727  bool hasDataDefinedAspectRatio = false;
2728  double aspectRatio = calculateAspectRatio( context, scaledSize, hasDataDefinedAspectRatio );
2729 
2730  QPointF outputOffset;
2731  double angle = 0.0;
2732 
2733  // RenderPercentage Unit Type takes original image size
2735  {
2737  if ( size.isEmpty() )
2738  return;
2739 
2740  width = ( scaledSize * static_cast< double >( size.width() ) ) / 100.0;
2741  height = ( scaledSize * static_cast< double >( size.height() ) ) / 100.0;
2742 
2743  // don't render symbols with size below one or above 10,000 pixels
2744  if ( static_cast< int >( width ) < 1 || 10000.0 < width || static_cast< int >( height ) < 1 || 10000.0 < height )
2745  return;
2746 
2747  calculateOffsetAndRotation( context, width, height, outputOffset, angle );
2748  }
2749  else
2750  {
2751  width = context.renderContext().convertToPainterUnits( scaledSize, mSizeUnit, mSizeMapUnitScale );
2752  height = width * ( preservedAspectRatio() ? defaultAspectRatio() : aspectRatio );
2753 
2754  if ( preservedAspectRatio() && path != mPath )
2755  {
2757  if ( !size.isNull() && size.isValid() && size.width() > 0 )
2758  {
2759  height = width * ( static_cast< double >( size.height() ) / static_cast< double >( size.width() ) );
2760  }
2761  }
2762 
2763  // don't render symbols with size below one or above 10,000 pixels
2764  if ( static_cast< int >( width ) < 1 || 10000.0 < width )
2765  return;
2766 
2767  calculateOffsetAndRotation( context, scaledSize, scaledSize * ( height / width ), outputOffset, angle );
2768  }
2769 
2770  p->save();
2771  p->translate( point + outputOffset );
2772 
2773  bool rotated = !qgsDoubleNear( angle, 0 );
2774  if ( rotated )
2775  p->rotate( angle );
2776 
2777  double opacity = mOpacity;
2779  {
2782  }
2783  opacity *= context.opacity();
2784 
2785  bool cached;
2786  QImage img = QgsApplication::imageCache()->pathAsImage( path, QSize( width, preservedAspectRatio() ? 0 : width * aspectRatio ), preservedAspectRatio(), opacity, cached, ( context.renderContext().flags() & QgsRenderContext::RenderBlocking ) );
2787  if ( !img.isNull() )
2788  {
2789  if ( context.selected() )
2791 
2792  p->drawImage( -img.width() / 2.0, -img.height() / 2.0, img );
2793  }
2794 
2795  p->restore();
2796 }
2797 
2798 double QgsRasterMarkerSymbolLayer::calculateSize( QgsSymbolRenderContext &context, bool &hasDataDefinedSize ) const
2799 {
2800  double scaledSize = mSize;
2802 
2803  bool ok = true;
2804  if ( hasDataDefinedSize )
2805  {
2806  context.setOriginalValueVariable( mSize );
2808  }
2809  else
2810  {
2812  if ( hasDataDefinedSize )
2813  {
2814  context.setOriginalValueVariable( mSize );
2816  }
2817  }
2818 
2819  if ( hasDataDefinedSize && ok )
2820  {
2821  switch ( mScaleMethod )
2822  {
2823  case QgsSymbol::ScaleArea:
2824  scaledSize = std::sqrt( scaledSize );
2825  break;
2827  break;
2828  }
2829  }
2830 
2831  return scaledSize;
2832 }
2833 
2834 double QgsRasterMarkerSymbolLayer::calculateAspectRatio( QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedAspectRatio ) const
2835 {
2837  if ( !hasDataDefinedAspectRatio )
2838  return mFixedAspectRatio;
2839 
2841  return 0.0;
2842 
2843  double scaledAspectRatio = mDefaultAspectRatio;
2844  if ( mFixedAspectRatio > 0.0 )
2845  scaledAspectRatio = mFixedAspectRatio;
2846 
2847  double defaultHeight = mSize * scaledAspectRatio;
2848  scaledAspectRatio = defaultHeight / scaledSize;
2849 
2850  bool ok = true;
2851  double scaledHeight = scaledSize * scaledAspectRatio;
2853  {
2854  context.setOriginalValueVariable( defaultHeight );
2855  scaledHeight = mDataDefinedProperties.valueAsDouble( QgsSymbolLayer::PropertyHeight, context.renderContext().expressionContext(), defaultHeight, &ok );
2856  }
2857 
2858  if ( hasDataDefinedAspectRatio && ok )
2859  {
2860  switch ( mScaleMethod )
2861  {
2862  case QgsSymbol::ScaleArea:
2863  scaledHeight = sqrt( scaledHeight );
2864  break;
2866  break;
2867  }
2868  }
2869 
2870  scaledAspectRatio = scaledHeight / scaledSize;
2871 
2872  return scaledAspectRatio;
2873 }
2874 
2875 void QgsRasterMarkerSymbolLayer::calculateOffsetAndRotation( QgsSymbolRenderContext &context, double scaledWidth, double scaledHeight, QPointF &offset, double &angle ) const
2876 {
2877  //offset
2878  double offsetX = 0;
2879  double offsetY = 0;
2880  markerOffset( context, scaledWidth, scaledHeight, offsetX, offsetY );
2881  offset = QPointF( offsetX, offsetY );
2882 
2883  angle = mAngle + mLineAngle;
2885  {
2886  context.setOriginalValueVariable( mAngle );
2888  }
2889 
2891  if ( hasDataDefinedRotation )
2892  {
2893  const QgsFeature *f = context.feature();
2894  if ( f )
2895  {
2896  if ( f->hasGeometry() && f->geometry().type() == QgsWkbTypes::PointGeometry )
2897  {
2898  const QgsMapToPixel &m2p = context.renderContext().mapToPixel();
2899  angle += m2p.mapRotation();
2900  }
2901  }
2902  }
2903 
2904  if ( angle )
2906 }
2907 
2908 
2910 {
2911  QgsStringMap map;
2912  map[QStringLiteral( "imageFile" )] = mPath;
2913  map[QStringLiteral( "size" )] = QString::number( mSize );
2914  map[QStringLiteral( "size_unit" )] = QgsUnitTypes::encodeUnit( mSizeUnit );
2915  map[QStringLiteral( "size_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mSizeMapUnitScale );
2916  map[QStringLiteral( "fixedAspectRatio" )] = QString::number( mFixedAspectRatio );
2917  map[QStringLiteral( "angle" )] = QString::number( mAngle );
2918  map[QStringLiteral( "alpha" )] = QString::number( mOpacity );
2919  map[QStringLiteral( "offset" )] = QgsSymbolLayerUtils::encodePoint( mOffset );
2920  map[QStringLiteral( "offset_unit" )] = QgsUnitTypes::encodeUnit( mOffsetUnit );
2921  map[QStringLiteral( "offset_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mOffsetMapUnitScale );
2922  map[QStringLiteral( "scale_method" )] = QgsSymbolLayerUtils::encodeScaleMethod( mScaleMethod );
2923  map[QStringLiteral( "horizontal_anchor_point" )] = QString::number( mHorizontalAnchorPoint );
2924  map[QStringLiteral( "vertical_anchor_point" )] = QString::number( mVerticalAnchorPoint );
2925  return map;
2926 }
2927 
2929 {
2932  m->setOpacity( mOpacity );
2933  m->setOffset( mOffset );
2934  m->setOffsetUnit( mOffsetUnit );
2936  m->setSizeUnit( mSizeUnit );
2941  copyPaintEffect( m );
2942  return m;
2943 }
2944 
2946 {
2948 }
2949 
2951 {
2953 }
2954 
2956 {
2957  bool hasDataDefinedSize = false;
2958  double scaledSize = calculateSize( context, hasDataDefinedSize );
2959  double width = context.renderContext().convertToPainterUnits( scaledSize, mSizeUnit, mSizeMapUnitScale );
2960  bool hasDataDefinedAspectRatio = false;
2961  double aspectRatio = calculateAspectRatio( context, scaledSize, hasDataDefinedAspectRatio );
2962  double height = width * ( preservedAspectRatio() ? defaultAspectRatio() : aspectRatio );
2963 
2964  //don't render symbols with size below one or above 10,000 pixels
2965  if ( static_cast< int >( scaledSize ) < 1 || 10000.0 < scaledSize )
2966  {
2967  return QRectF();
2968  }
2969 
2970  QPointF outputOffset;
2971  double angle = 0.0;
2972  calculateOffsetAndRotation( context, scaledSize, scaledSize * ( height / width ), outputOffset, angle );
2973 
2974  QMatrix transform;
2975 
2976  // move to the desired position
2977  transform.translate( point.x() + outputOffset.x(), point.y() + outputOffset.y() );
2978 
2979  if ( !qgsDoubleNear( angle, 0.0 ) )
2980  transform.rotate( angle );
2981 
2982  QRectF symbolBounds = transform.mapRect( QRectF( -width / 2.0,
2983  -height / 2.0,
2984  width,
2985  height ) );
2986 
2987  return symbolBounds;
2988 }
2989 
2991 
2992 QgsFontMarkerSymbolLayer::QgsFontMarkerSymbolLayer( const QString &fontFamily, QString chr, double pointSize, const QColor &color, double angle )
2993 {
2994  mFontFamily = fontFamily;
2995  mString = chr;
2996  mColor = color;
2997  mAngle = angle;
2998  mSize = pointSize;
2999  mOrigSize = pointSize;
3001  mOffset = QPointF( 0, 0 );
3003  mStrokeColor = DEFAULT_FONTMARKER_BORDERCOLOR;
3004  mStrokeWidth = 0.0;
3005  mStrokeWidthUnit = QgsUnitTypes::RenderMillimeters;
3006  mPenJoinStyle = DEFAULT_FONTMARKER_JOINSTYLE;
3007 }
3008 
3010 {
3013  QString string = DEFAULT_FONTMARKER_CHR;
3014  double pointSize = DEFAULT_FONTMARKER_SIZE;
3017 
3018  if ( props.contains( QStringLiteral( "font" ) ) )
3019  fontFamily = props[QStringLiteral( "font" )];
3020  if ( props.contains( QStringLiteral( "chr" ) ) && props[QStringLiteral( "chr" )].length() > 0 )
3021  string = props[QStringLiteral( "chr" )];
3022  if ( props.contains( QStringLiteral( "size" ) ) )
3023  pointSize = props[QStringLiteral( "size" )].toDouble();
3024  if ( props.contains( QStringLiteral( "color" ) ) )
3025  color = QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "color" )] );
3026  if ( props.contains( QStringLiteral( "angle" ) ) )
3027  angle = props[QStringLiteral( "angle" )].toDouble();
3028 
3029  QgsFontMarkerSymbolLayer *m = new QgsFontMarkerSymbolLayer( fontFamily, string, pointSize, color, angle );
3030 
3031  if ( props.contains( QStringLiteral( "font_style" ) ) )
3032  m->setFontStyle( props[QStringLiteral( "font_style" )] );
3033  if ( props.contains( QStringLiteral( "outline_color" ) ) )
3034  m->setStrokeColor( QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "outline_color" )] ) );
3035  if ( props.contains( QStringLiteral( "outline_width" ) ) )
3036  m->setStrokeWidth( props[QStringLiteral( "outline_width" )].toDouble() );
3037  if ( props.contains( QStringLiteral( "offset" ) ) )
3038  m->setOffset( QgsSymbolLayerUtils::decodePoint( props[QStringLiteral( "offset" )] ) );
3039  if ( props.contains( QStringLiteral( "offset_unit" ) ) )
3040  m->setOffsetUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "offset_unit" )] ) );
3041  if ( props.contains( QStringLiteral( "offset_map_unit_scale" ) ) )
3042  m->setOffsetMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "offset_map_unit_scale" )] ) );
3043  if ( props.contains( QStringLiteral( "size_unit" ) ) )
3044  m->setSizeUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "size_unit" )] ) );
3045  if ( props.contains( QStringLiteral( "size_map_unit_scale" ) ) )
3046  m->setSizeMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "size_map_unit_scale" )] ) );
3047  if ( props.contains( QStringLiteral( "outline_width_unit" ) ) )
3048  m->setStrokeWidthUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "outline_width_unit" )] ) );
3049  if ( props.contains( QStringLiteral( "outline_width_map_unit_scale" ) ) )
3050  m->setStrokeWidthMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "outline_width_map_unit_scale" )] ) );
3051  if ( props.contains( QStringLiteral( "joinstyle" ) ) )
3052  m->setPenJoinStyle( QgsSymbolLayerUtils::decodePenJoinStyle( props[QStringLiteral( "joinstyle" )] ) );
3053  if ( props.contains( QStringLiteral( "horizontal_anchor_point" ) ) )
3054  m->setHorizontalAnchorPoint( QgsMarkerSymbolLayer::HorizontalAnchorPoint( props[ QStringLiteral( "horizontal_anchor_point" )].toInt() ) );
3055  if ( props.contains( QStringLiteral( "vertical_anchor_point" ) ) )
3056  m->setVerticalAnchorPoint( QgsMarkerSymbolLayer::VerticalAnchorPoint( props[ QStringLiteral( "vertical_anchor_point" )].toInt() ) );
3057 
3058  m->restoreOldDataDefinedProperties( props );
3059 
3060  return m;
3061 }
3062 
3064 {
3065  return QStringLiteral( "FontMarker" );
3066 }
3067 
3069 {
3070  QColor brushColor = mColor;
3071  QColor penColor = mStrokeColor;
3072 
3073  brushColor.setAlphaF( mColor.alphaF() * context.opacity() );
3074  penColor.setAlphaF( mStrokeColor.alphaF() * context.opacity() );
3075 
3076  mBrush = QBrush( brushColor );
3077  mPen = QPen( penColor );
3078  mPen.setJoinStyle( mPenJoinStyle );
3079  mPen.setWidthF( context.renderContext().convertToPainterUnits( mStrokeWidth, mStrokeWidthUnit, mStrokeWidthMapUnitScale ) );
3080 
3081  mFont = QFont( mFontFamily );
3082  if ( !mFontStyle.isEmpty() )
3083  {
3084  mFont.setStyleName( QgsFontUtils::translateNamedStyle( mFontStyle ) );
3085  }
3086 
3087  const double sizePixels = context.renderContext().convertToPainterUnits( mSize, mSizeUnit, mSizeMapUnitScale );
3088  mNonZeroFontSize = !qgsDoubleNear( sizePixels, 0.0 );
3089  // if a non zero, but small pixel size results, round up to 2 pixels so that a "dot" is at least visible
3090  // (if we set a <=1 pixel size here Qt will reset the font to a default size, leading to much too large symbols)
3091  mFont.setPixelSize( std::max( 2, static_cast< int >( std::round( sizePixels ) ) ) );
3092  mFontMetrics.reset( new QFontMetrics( mFont ) );
3093 #if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
3094  mChrWidth = mFontMetrics->width( mString );
3095 #else
3096  mChrWidth = mFontMetrics->horizontalAdvance( mString );
3097 #endif
3098  mChrOffset = QPointF( mChrWidth / 2.0, -mFontMetrics->ascent() / 2.0 );
3099  mOrigSize = mSize; // save in case the size would be data defined
3100 
3101  // use caching only when not using a data defined character
3105  if ( mUseCachedPath )
3106  {
3107  QPointF chrOffset = mChrOffset;
3108  double chrWidth;
3109  QString charToRender = characterToRender( context, chrOffset, chrWidth );
3110  mCachedPath = QPainterPath();
3111  mCachedPath.addText( -chrOffset.x(), -chrOffset.y(), mFont, charToRender );
3112  }
3113 }
3114 
3116 {
3117  Q_UNUSED( context )
3118 }
3119 
3120 QString QgsFontMarkerSymbolLayer::characterToRender( QgsSymbolRenderContext &context, QPointF &charOffset, double &charWidth )
3121 {
3122  charOffset = mChrOffset;
3123  QString stringToRender = mString;
3125  {
3126  context.setOriginalValueVariable( mString );
3128  if ( stringToRender != mString )
3129  {
3130 #if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
3131  charWidth = mFontMetrics->width( stringToRender );
3132 #else
3133  charWidth = mFontMetrics->horizontalAdvance( stringToRender );
3134 #endif
3135  charOffset = QPointF( charWidth / 2.0, -mFontMetrics->ascent() / 2.0 );
3136  }
3137  }
3138  return stringToRender;
3139 }
3140 
3141 void QgsFontMarkerSymbolLayer::calculateOffsetAndRotation( QgsSymbolRenderContext &context,
3142  double scaledSize,
3143  bool &hasDataDefinedRotation,
3144  QPointF &offset,
3145  double &angle ) const
3146 {
3147  //offset
3148  double offsetX = 0;
3149  double offsetY = 0;
3150  markerOffset( context, scaledSize, scaledSize, offsetX, offsetY );
3151  offset = QPointF( offsetX, offsetY );
3152 
3153  //angle
3154  bool ok = true;
3155  angle = mAngle + mLineAngle;
3157  {
3158  context.setOriginalValueVariable( angle );
3160 
3161  // If the expression evaluation was not successful, fallback to static value
3162  if ( !ok )
3163  angle = mAngle + mLineAngle;
3164  }
3165 
3166  hasDataDefinedRotation = context.renderHints() & QgsSymbol::DynamicRotation;
3167  if ( hasDataDefinedRotation )
3168  {
3169  // For non-point markers, "dataDefinedRotation" means following the
3170  // shape (shape-data defined). For them, "field-data defined" does
3171  // not work at all. TODO: if "field-data defined" ever gets implemented
3172  // we'll need a way to distinguish here between the two, possibly
3173  // using another flag in renderHints()
3174  const QgsFeature *f = context.feature();
3175  if ( f )
3176  {
3177  if ( f->hasGeometry() && f->geometry().type() == QgsWkbTypes::PointGeometry )
3178  {
3179  const QgsMapToPixel &m2p = context.renderContext().mapToPixel();
3180  angle += m2p.mapRotation();
3181  }
3182  }
3183  }
3184 
3185  if ( angle )
3187 }
3188 
3189 double QgsFontMarkerSymbolLayer::calculateSize( QgsSymbolRenderContext &context )
3190 {
3191  double scaledSize = mSize;
3192  bool hasDataDefinedSize = mDataDefinedProperties.isActive( QgsSymbolLayer::PropertySize );
3193 
3194  bool ok = true;
3195  if ( hasDataDefinedSize )
3196  {
3197  context.setOriginalValueVariable( mSize );
3199  }
3200 
3201  if ( hasDataDefinedSize && ok )
3202  {
3203  switch ( mScaleMethod )
3204  {
3205  case QgsSymbol::ScaleArea:
3206  scaledSize = std::sqrt( scaledSize );
3207  break;
3209  break;
3210  }
3211  }
3212  return scaledSize;
3213 }
3214 
3216 {
3217  QPainter *p = context.renderContext().painter();
3218  if ( !p || !mNonZeroFontSize )
3219  return;
3220 
3221  QTransform transform;
3222 
3223  bool ok;
3224  QColor brushColor = mColor;
3226  {
3229  }
3230  brushColor = context.selected() ? context.renderContext().selectionColor() : brushColor;
3231  if ( !SELECTION_IS_OPAQUE )
3232  {
3233  brushColor.setAlphaF( brushColor.alphaF() * context.opacity() );
3234  }
3235  mBrush.setColor( brushColor );
3236 
3237  QColor penColor = mStrokeColor;
3239  {
3242  }
3243  penColor.setAlphaF( penColor.alphaF() * context.opacity() );
3244 
3245  double penWidth = context.renderContext().convertToPainterUnits( mStrokeWidth, mStrokeWidthUnit, mStrokeWidthMapUnitScale );
3247  {
3248  context.setOriginalValueVariable( mStrokeWidth );
3250  if ( ok )
3251  {
3252  penWidth = context.renderContext().convertToPainterUnits( strokeWidth, mStrokeWidthUnit, mStrokeWidthMapUnitScale );
3253  }
3254  }
3255 
3257  {
3260  if ( ok )
3261  {
3262  mPen.setJoinStyle( QgsSymbolLayerUtils::decodePenJoinStyle( style ) );
3263  }
3264  }
3265 
3266  p->save();
3267  p->setBrush( mBrush );
3268  if ( !qgsDoubleNear( penWidth, 0.0 ) )
3269  {
3270  mPen.setColor( penColor );
3271  mPen.setWidthF( penWidth );
3272  p->setPen( mPen );
3273  }
3274  else
3275  {
3276  p->setPen( Qt::NoPen );
3277  }
3278 
3280  {
3281  context.setOriginalValueVariable( mFontFamily );
3283  mFont.setFamily( ok ? fontFamily : mFontFamily );
3284  }
3286  {
3287  context.setOriginalValueVariable( mFontStyle );
3289  mFont.setStyleName( QgsFontUtils::translateNamedStyle( ok ? fontStyle : mFontStyle ) );
3290  }
3292  {
3293  mFontMetrics.reset( new QFontMetrics( mFont ) );
3294  }
3295 
3296  QPointF chrOffset = mChrOffset;
3297  double chrWidth;
3298  QString charToRender = characterToRender( context, chrOffset, chrWidth );
3299 
3300  double sizeToRender = calculateSize( context );
3301 
3302  bool hasDataDefinedRotation = false;
3303  QPointF offset;
3304  double angle = 0;
3305  calculateOffsetAndRotation( context, sizeToRender, hasDataDefinedRotation, offset, angle );
3306 
3307  p->translate( point.x() + offset.x(), point.y() + offset.y() );
3308 
3309  if ( !qgsDoubleNear( angle, 0.0 ) )
3310  transform.rotate( angle );
3311 
3312  if ( !qgsDoubleNear( sizeToRender, mOrigSize ) )
3313  {
3314  double s = sizeToRender / mOrigSize;
3315  transform.scale( s, s );
3316  }
3317 
3318  if ( mUseCachedPath )
3319  {
3320  p->drawPath( transform.map( mCachedPath ) );
3321  }
3322  else
3323  {
3324  QPainterPath path;
3325  path.addText( -chrOffset.x(), -chrOffset.y(), mFont, charToRender );
3326  p->drawPath( transform.map( path ) );
3327  }
3328 
3329  p->restore();
3330 }
3331 
3333 {
3334  QgsStringMap props;
3335  props[QStringLiteral( "font" )] = mFontFamily;
3336  props[QStringLiteral( "font_style" )] = mFontStyle;
3337  props[QStringLiteral( "chr" )] = mString;
3338  props[QStringLiteral( "size" )] = QString::number( mSize );
3339  props[QStringLiteral( "size_unit" )] = QgsUnitTypes::encodeUnit( mSizeUnit );
3340  props[QStringLiteral( "size_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mSizeMapUnitScale );
3341  props[QStringLiteral( "color" )] = QgsSymbolLayerUtils::encodeColor( mColor );
3342  props[QStringLiteral( "outline_color" )] = QgsSymbolLayerUtils::encodeColor( mStrokeColor );
3343  props[QStringLiteral( "outline_width" )] = QString::number( mStrokeWidth );
3344  props[QStringLiteral( "outline_width_unit" )] = QgsUnitTypes::encodeUnit( mStrokeWidthUnit );
3345  props[QStringLiteral( "outline_width_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mStrokeWidthMapUnitScale );
3346  props[QStringLiteral( "joinstyle" )] = QgsSymbolLayerUtils::encodePenJoinStyle( mPenJoinStyle );
3347  props[QStringLiteral( "angle" )] = QString::number( mAngle );
3348  props[QStringLiteral( "offset" )] = QgsSymbolLayerUtils::encodePoint( mOffset );
3349  props[QStringLiteral( "offset_unit" )] = QgsUnitTypes::encodeUnit( mOffsetUnit );
3350  props[QStringLiteral( "offset_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mOffsetMapUnitScale );
3351  props[QStringLiteral( "horizontal_anchor_point" )] = QString::number( mHorizontalAnchorPoint );
3352  props[QStringLiteral( "vertical_anchor_point" )] = QString::number( mVerticalAnchorPoint );
3353  return props;
3354 }
3355 
3357 {
3358  QgsFontMarkerSymbolLayer *m = new QgsFontMarkerSymbolLayer( mFontFamily, mString, mSize, mColor, mAngle );
3359  m->setFontStyle( mFontStyle );
3360  m->setStrokeColor( mStrokeColor );
3361  m->setStrokeWidth( mStrokeWidth );
3362  m->setStrokeWidthUnit( mStrokeWidthUnit );
3363  m->setStrokeWidthMapUnitScale( mStrokeWidthMapUnitScale );
3364  m->setPenJoinStyle( mPenJoinStyle );
3365  m->setOffset( mOffset );
3366  m->setOffsetUnit( mOffsetUnit );
3368  m->setSizeUnit( mSizeUnit );
3373  copyPaintEffect( m );
3374  return m;
3375 }
3376 
3377 void QgsFontMarkerSymbolLayer::writeSldMarker( QDomDocument &doc, QDomElement &element, const QgsStringMap &props ) const
3378 {
3379  // <Graphic>
3380  QDomElement graphicElem = doc.createElement( QStringLiteral( "se:Graphic" ) );
3381  element.appendChild( graphicElem );
3382 
3383  QString fontPath = QStringLiteral( "ttf://%1" ).arg( mFontFamily );
3384  int markIndex = !mString.isEmpty() ? mString.at( 0 ).unicode() : 0;
3386  QgsSymbolLayerUtils::externalMarkerToSld( doc, graphicElem, fontPath, QStringLiteral( "ttf" ), &markIndex, mColor, size );
3387 
3388  // <Rotation>
3389  QString angleFunc;
3390  bool ok;
3391  double angle = props.value( QStringLiteral( "angle" ), QStringLiteral( "0" ) ).toDouble( &ok );
3392  if ( !ok )
3393  {
3394  angleFunc = QStringLiteral( "%1 + %2" ).arg( props.value( QStringLiteral( "angle" ), QStringLiteral( "0" ) ) ).arg( mAngle );
3395  }
3396  else if ( !qgsDoubleNear( angle + mAngle, 0.0 ) )
3397  {
3398  angleFunc = QString::number( angle + mAngle );
3399  }
3400  QgsSymbolLayerUtils::createRotationElement( doc, graphicElem, angleFunc );
3401 
3402  // <Displacement>
3405 }
3406 
3408 {
3409  QPointF chrOffset = mChrOffset;
3410  double chrWidth = mChrWidth;
3411  //calculate width of rendered character
3412  ( void )characterToRender( context, chrOffset, chrWidth );
3413 
3414  if ( !mFontMetrics )
3415  mFontMetrics.reset( new QFontMetrics( mFont ) );
3416 
3417  double scaledSize = calculateSize( context );
3418  if ( !qgsDoubleNear( scaledSize, mOrigSize ) )
3419  {
3420  chrWidth *= scaledSize / mOrigSize;
3421  }
3422 
3423  bool hasDataDefinedRotation = false;
3424  QPointF offset;
3425  double angle = 0;
3426  calculateOffsetAndRotation( context, scaledSize, hasDataDefinedRotation, offset, angle );
3427  scaledSize = context.renderContext().convertToPainterUnits( scaledSize, mSizeUnit, mSizeMapUnitScale );
3428 
3429  QMatrix transform;
3430 
3431  // move to the desired position
3432  transform.translate( point.x() + offset.x(), point.y() + offset.y() );
3433 
3434  if ( !qgsDoubleNear( angle, 0.0 ) )
3435  transform.rotate( angle );
3436 
3437  QRectF symbolBounds = transform.mapRect( QRectF( -chrWidth / 2.0,
3438  -scaledSize / 2.0,
3439  chrWidth,
3440  scaledSize ) );
3441  return symbolBounds;
3442 }
3443 
3445 {
3446  QgsDebugMsgLevel( QStringLiteral( "Entered." ), 4 );
3447 
3448  QDomElement graphicElem = element.firstChildElement( QStringLiteral( "Graphic" ) );
3449  if ( graphicElem.isNull() )
3450  return nullptr;
3451 
3452  QString name, format;
3453  QColor color;
3454  double size;
3455  int chr;
3456 
3457  if ( !QgsSymbolLayerUtils::externalMarkerFromSld( graphicElem, name, format, chr, color, size ) )
3458  return nullptr;
3459 
3460  if ( !name.startsWith( QLatin1String( "ttf://" ) ) || format != QLatin1String( "ttf" ) )
3461  return nullptr;
3462 
3463  QString fontFamily = name.mid( 6 );
3464 
3465  double angle = 0.0;
3466  QString angleFunc;
3467  if ( QgsSymbolLayerUtils::rotationFromSldElement( graphicElem, angleFunc ) )
3468  {
3469  bool ok;
3470  double d = angleFunc.toDouble( &ok );
3471  if ( ok )
3472  angle = d;
3473  }
3474 
3475  QPointF offset;
3477 
3478  QString uom = element.attribute( QStringLiteral( "uom" ) );
3482 
3484  m->setOutputUnit( QgsUnitTypes::RenderUnit::RenderPixels );
3485  m->setAngle( angle );
3486  m->setOffset( offset );
3487  return m;
3488 }
3489 
QgsSimpleMarkerSymbolLayerBase::Arrow
@ Arrow
Arrow.
Definition: qgsmarkersymbollayer.h:57
QgsSymbolRenderContext::setOriginalValueVariable
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for data defined symbology.
Definition: qgssymbol.cpp:1370
QgsFilledMarkerSymbolLayer::setColor
void setColor(const QColor &c) override
The fill color.
Definition: qgsmarkersymbollayer.cpp:1695
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:723
QgsRasterMarkerSymbolLayer::mFixedAspectRatio
double mFixedAspectRatio
The marker fixed aspect ratio.
Definition: qgsmarkersymbollayer.h:774
QgsMarkerSymbolLayer::setSizeUnit
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the symbol's size.
Definition: qgssymbollayer.h:664
qgssvgcache.h
QgsSvgMarkerSymbolLayer::mapUnitScale
QgsMapUnitScale mapUnitScale() const override
Definition: qgsmarkersymbollayer.cpp:2313
QgsSvgMarkerSymbolLayer::layerType
QString layerType() const override
Returns a string that represents this layer type.
Definition: qgsmarkersymbollayer.cpp:1983
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
QgsSymbolLayerUtils::encodeColor
static QString encodeColor(const QColor &color)
Definition: qgssymbollayerutils.cpp:52
QgsMarkerSymbolLayer::setHorizontalAnchorPoint
void setHorizontalAnchorPoint(HorizontalAnchorPoint h)
Sets the horizontal anchor point for positioning the symbol.
Definition: qgssymbollayer.h:764
QgsMarkerSymbolLayer::VerticalAnchorPoint
VerticalAnchorPoint
Symbol vertical anchor points.
Definition: qgssymbollayer.h:588
QgsRasterMarkerSymbolLayer::renderPoint
void renderPoint(QPointF point, QgsSymbolRenderContext &context) override
Renders a marker at the specified point.
Definition: qgsmarkersymbollayer.cpp:2705
QgsRenderContext::convertToPainterUnits
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels).
Definition: qgsrendercontext.cpp:287
QgsSymbolLayer::mColor
QColor mColor
Definition: qgssymbollayer.h:521
QgsFilledMarkerSymbolLayer
Filled marker symbol layer, consisting of a shape which is rendered using a QgsFillSymbol....
Definition: qgsmarkersymbollayer.h:426
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:309
QgsSimpleMarkerSymbolLayer::setStrokeWidthMapUnitScale
void setStrokeWidthMapUnitScale(const QgsMapUnitScale &scale)
Sets the map scale for the width of the marker's stroke.
Definition: qgsmarkersymbollayer.h:354
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:157
QgsMarkerSymbolLayer::size
double size() const
Returns the symbol size.
Definition: qgssymbollayer.h:655
DEFAULT_SIMPLEMARKER_ANGLE
#define DEFAULT_SIMPLEMARKER_ANGLE
Definition: qgsmarkersymbollayer.h:28
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:2516
QgsRasterMarkerSymbolLayer::opacity
double opacity() const
Returns the marker opacity.
Definition: qgsmarkersymbollayer.h:710
QgsUnitTypes::RenderUnit
RenderUnit
Rendering size units.
Definition: qgsunittypes.h:166
QgsSimpleMarkerSymbolLayer::strokeStyle
Qt::PenStyle strokeStyle() const
Returns the marker's stroke style (e.g., solid, dashed, etc)
Definition: qgsmarkersymbollayer.h:282
QgsSvgMarkerSymbolLayer::mDefaultAspectRatio
double mDefaultAspectRatio
The marker default aspect ratio.
Definition: qgsmarkersymbollayer.h:622
QgsSimpleMarkerSymbolLayer::renderPoint
void renderPoint(QPointF point, QgsSymbolRenderContext &context) override
Renders a marker at the specified point.
Definition: qgsmarkersymbollayer.cpp:1026
QgsDxfExport
Definition: qgsdxfexport.h:62
QgsMarkerSymbolLayer::mSizeMapUnitScale
QgsMapUnitScale mSizeMapUnitScale
Marker size map unit scale.
Definition: qgssymbollayer.h:867
QgsFontMarkerSymbolLayer::setStrokeWidth
void setStrokeWidth(double width)
Set's the marker's stroke width.
Definition: qgsmarkersymbollayer.h:908
QgsSimpleMarkerSymbolLayer::penJoinStyle
Qt::PenJoinStyle penJoinStyle() const
Returns the marker's stroke join style (e.g., miter, bevel, etc).
Definition: qgsmarkersymbollayer.h:301
QgsSvgMarkerSymbolLayer::setOutputUnit
void setOutputUnit(QgsUnitTypes::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
Definition: qgsmarkersymbollayer.cpp:2291
QgsRenderContext::expressionContext
QgsExpressionContext & expressionContext()
Gets the expression context.
Definition: qgsrendercontext.h:580
QgsFilledMarkerSymbolLayer::usedAttributes
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
Definition: qgsmarkersymbollayer.cpp:1678
QgsMapToPixel::mapUnitsPerPixel
double mapUnitsPerPixel() const
Returns current map units per pixel.
Definition: qgsmaptopixel.cpp:128
QgsSymbolLayerUtils::externalGraphicFromSld
static bool externalGraphicFromSld(QDomElement &element, QString &path, QString &mime, QColor &color, double &size)
Definition: qgssymbollayerutils.cpp:2297
DEFAULT_SIMPLEMARKER_NAME
#define DEFAULT_SIMPLEMARKER_NAME
Definition: qgsmarkersymbollayer.h:23
QgsSymbolLayerUtils::wellKnownMarkerFromSld
static bool wellKnownMarkerFromSld(QDomElement &element, QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle, double &strokeWidth, double &size)
Definition: qgssymbollayerutils.cpp:2432
QgsMarkerSymbolLayer::mapUnitScale
QgsMapUnitScale mapUnitScale() const override
Definition: qgssymbollayer.cpp:627
QgsSimpleMarkerSymbolLayerBase::Line
@ Line
Vertical line.
Definition: qgsmarkersymbollayer.h:62
QgsFontMarkerSymbolLayer::properties
QgsStringMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
Definition: qgsmarkersymbollayer.cpp:3332
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:2992
QgsSymbolLayerUtils::encodeMapUnitScale
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
Definition: qgssymbollayerutils.cpp:558
QgsPoint
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
QgsDxfExport::writePolygon
void writePolygon(const QgsRingSequence &polygon, const QString &layer, const QString &hatchPattern, const QColor &color)
Draw dxf filled polygon (HATCH)
Definition: qgsdxfexport.cpp:1163
QgsSymbolLayerUtils::sizeInPixelsFromSldUom
static double sizeInPixelsFromSldUom(const QString &uom, double size)
Returns the size scaled in pixels according to the uom attribute.
Definition: qgssymbollayerutils.cpp:4397
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QgsSymbolRenderContext::feature
const QgsFeature * feature() const
Returns the current feature being rendered.
Definition: qgssymbol.h:789
qgsexpression.h
QgsSimpleMarkerSymbolLayerBase::Triangle
@ Triangle
Triangle.
Definition: qgsmarkersymbollayer.h:54
QgsDxfPaintDevice::setDrawingSize
void setDrawingSize(QSizeF size)
Definition: qgsdxfpaintdevice.h:45
QgsSimpleMarkerSymbolLayer::setOutputUnit
void setOutputUnit(QgsUnitTypes::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
Definition: qgsmarkersymbollayer.cpp:1447
QgsSimpleMarkerSymbolLayer::mPenJoinStyle
Qt::PenJoinStyle mPenJoinStyle
Stroke pen join style.
Definition: qgsmarkersymbollayer.h:391
QgsSymbolLayerUtils::externalMarkerFromSld
static bool externalMarkerFromSld(QDomElement &element, QString &path, QString &format, int &markIndex, QColor &color, double &size)
Definition: qgssymbollayerutils.cpp:2352
QgsSymbolLayer::PropertyFontFamily
@ PropertyFontFamily
Font family.
Definition: qgssymbollayer.h:189
QgsSymbolLayer::setColor
virtual void setColor(const QColor &color)
The fill color.
Definition: qgssymbollayer.h:231
QgsSimpleMarkerSymbolLayer::mSelCache
QImage mSelCache
Cached image of selected marker, if using cached version.
Definition: qgsmarkersymbollayer.h:404
QgsSymbolLayer::color
virtual QColor color() const
The fill color.
Definition: qgssymbollayer.h:226
QgsSymbolLayer::PropertyFillColor
@ PropertyFillColor
Fill color.
Definition: qgssymbollayer.h:135
QgsSimpleMarkerSymbolLayerBase::startRender
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
Definition: qgsmarkersymbollayer.cpp:134
QgsFilledMarkerSymbolLayer::properties
QgsStringMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
Definition: qgsmarkersymbollayer.cpp:1619
QgsSymbolLayerUtils::decodeScaleMethod
static QgsSymbol::ScaleMethod decodeScaleMethod(const QString &str)
Definition: qgssymbollayerutils.cpp:729
QgsSimpleMarkerSymbolLayerBase::Hexagon
@ Hexagon
Hexagon.
Definition: qgsmarkersymbollayer.h:53
QgsSimpleMarkerSymbolLayerBase::SemiCircle
@ SemiCircle
Semi circle (top half)
Definition: qgsmarkersymbollayer.h:65
DEFAULT_FONTMARKER_ANGLE
#define DEFAULT_FONTMARKER_ANGLE
Definition: qgsmarkersymbollayer.h:794
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:1669
QgsMarkerSymbolLayer::setAngle
void setAngle(double angle)
Sets the rotation angle for the marker.
Definition: qgssymbollayer.h:621
QgsSymbolRenderContext::opacity
qreal opacity() const
Returns the opacity for the symbol.
Definition: qgssymbol.h:751
QgsRasterMarkerSymbolLayer::updateDefaultAspectRatio
double updateDefaultAspectRatio()
Calculates the default marker aspect ratio between width and height.
Definition: qgsmarkersymbollayer.cpp:2690
QgsMarkerSymbolLayer::scaleMethod
QgsSymbol::ScaleMethod scaleMethod() const
Returns the method to use for scaling the marker's size.
Definition: qgssymbollayer.h:702
QgsSvgMarkerSymbolLayer::setPath
void setPath(const QString &path)
Set the marker SVG path.
Definition: qgsmarkersymbollayer.cpp:1907
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:215
QgsFilledMarkerSymbolLayer::create
static QgsSymbolLayer * create(const QgsStringMap &properties=QgsStringMap())
Creates a new QgsFilledMarkerSymbolLayer.
Definition: qgsmarkersymbollayer.cpp:1553
qgsmarkersymbollayer.h
QgsSimpleMarkerSymbolLayer::properties
QgsStringMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
Definition: qgsmarkersymbollayer.cpp:1060
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:71
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)
Gets SVG as QImage.
Definition: qgssvgcache.cpp:122
QgsRasterMarkerSymbolLayer::properties
QgsStringMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
Definition: qgsmarkersymbollayer.cpp:2909
QgsSimpleMarkerSymbolLayerBase::QuarterSquare
@ QuarterSquare
Quarter square (top left quarter)
Definition: qgsmarkersymbollayer.h:68
QgsUnitTypes::RenderPercentage
@ RenderPercentage
Percentage of another measurement (e.g., canvas size, feature size)
Definition: qgsunittypes.h:171
QgsMarkerSymbolLayer::startRender
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
Definition: qgssymbollayer.cpp:443
QgsRenderContext
Definition: qgsrendercontext.h:57
QgsSymbol::ScaleDiameter
@ ScaleDiameter
Calculate scale by the diameter.
Definition: qgssymbol.h:99
DEFAULT_RASTERMARKER_SIZE
#define DEFAULT_RASTERMARKER_SIZE
Definition: qgsmarkersymbollayer.h:641
QgsSymbolLayerUtils::multiplyImageOpacity
static void multiplyImageOpacity(QImage *image, qreal opacity)
Multiplies opacity of image pixel values with a (global) transparency value.
Definition: qgssymbollayerutils.cpp:3675
QgsSymbolLayer::SELECTION_IS_OPAQUE
static const bool SELECTION_IS_OPAQUE
Whether styles for selected features ignore symbol alpha.
Definition: qgssymbollayer.h:531
QgsSimpleMarkerSymbolLayer::setColor
void setColor(const QColor &color) override
The fill color.
Definition: qgsmarkersymbollayer.cpp:1516
qgsunittypes.h
QgsSimpleMarkerSymbolLayer::setStrokeStyle
void setStrokeStyle(Qt::PenStyle strokeStyle)
Sets the marker's stroke style (e.g., solid, dashed, etc)
Definition: qgsmarkersymbollayer.h:292
QgsMarkerSymbolLayer::mScaleMethod
QgsSymbol::ScaleMethod mScaleMethod
Marker size scaling method.
Definition: qgssymbollayer.h:875
QgsUnitTypes::RenderMillimeters
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:168
DEFAULT_FONTMARKER_FONT
#define DEFAULT_FONTMARKER_FONT
Definition: qgsmarkersymbollayer.h:788
QgsMarkerSymbolLayer
Abstract base class for marker symbol layers.
Definition: qgssymbollayer.h:575
QgsSimpleMarkerSymbolLayer::ogrFeatureStyle
QString ogrFeatureStyle(double mmScaleFactor, double mapUnitScaleFactor) const override
Definition: qgsmarkersymbollayer.cpp:1132
qgsdxfpaintdevice.h
QgsRasterMarkerSymbolLayer::setOpacity
void setOpacity(double opacity)
Set the marker opacity.
Definition: qgsmarkersymbollayer.h:717
QgsSymbol::ScaleMethod
ScaleMethod
Scale method.
Definition: qgssymbol.h:96
QgsFontMarkerSymbolLayer::setStrokeColor
void setStrokeColor(const QColor &color) override
Set stroke color.
Definition: qgsmarkersymbollayer.h:886
QgsSymbolLayerUtils::encodePenStyle
static QString encodePenStyle(Qt::PenStyle style)
Definition: qgssymbollayerutils.cpp:141
QgsRasterMarkerSymbolLayer::mapUnitScale
QgsMapUnitScale mapUnitScale() const override
Definition: qgsmarkersymbollayer.cpp:2950
DEFAULT_SIMPLEMARKER_JOINSTYLE
#define DEFAULT_SIMPLEMARKER_JOINSTYLE
Definition: qgsmarkersymbollayer.h:26
QgsSymbol
Definition: qgssymbol.h:63
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:2955
QgsMarkerSymbolLayer::setMapUnitScale
void setMapUnitScale(const QgsMapUnitScale &scale) override
Definition: qgssymbollayer.cpp:621
QgsSimpleMarkerSymbolLayer::clone
QgsSimpleMarkerSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
Definition: qgsmarkersymbollayer.cpp:1084
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:3945
QgsMarkerSymbolLayer::mSizeUnit
QgsUnitTypes::RenderUnit mSizeUnit
Marker size unit.
Definition: qgssymbollayer.h:865
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
qgsfontutils.h
QgsSimpleMarkerSymbolLayerBase::prepareMarkerShape
bool prepareMarkerShape(Shape shape)
Prepares the layer for drawing the specified shape (QPolygonF version)
Definition: qgsmarkersymbollayer.cpp:404
QgsRenderContext::scaleFactor
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
Definition: qgsrendercontext.h:317
QgsSymbolLayer::PropertyStrokeColor
@ PropertyStrokeColor
Stroke color.
Definition: qgssymbollayer.h:136
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:1263
QgsSvgMarkerSymbolLayer::setMapUnitScale
void setMapUnitScale(const QgsMapUnitScale &scale) override
Definition: qgsmarkersymbollayer.cpp:2307
QgsSimpleMarkerSymbolLayer::create
static QgsSymbolLayer * create(const QgsStringMap &properties=QgsStringMap())
Creates a new QgsSimpleMarkerSymbolLayer.
Definition: qgsmarkersymbollayer.cpp:715
QgsFilledMarkerSymbolLayer::startRender
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
Definition: qgsmarkersymbollayer.cpp:1601
QgsFilledMarkerSymbolLayer::color
QColor color() const override
The fill color.
Definition: qgsmarkersymbollayer.cpp:1702
QgsSymbolLayerUtils::decodeColor
static QColor decodeColor(const QString &str)
Definition: qgssymbollayerutils.cpp:57
QgsRasterMarkerSymbolLayer::clone
QgsRasterMarkerSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
Definition: qgsmarkersymbollayer.cpp:2928
QgsSvgMarkerSymbolLayer::createFromSld
static QgsSymbolLayer * createFromSld(QDomElement &element)
Definition: qgsmarkersymbollayer.cpp:2353
QgsMarkerSymbolLayer::mVerticalAnchorPoint
VerticalAnchorPoint mVerticalAnchorPoint
Vertical anchor point.
Definition: qgssymbollayer.h:879
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:1819
QgsSimpleMarkerSymbolLayerBase::prepareMarkerPath
bool prepareMarkerPath(Shape symbol)
Prepares the layer for drawing the specified shape (QPainterPath version)
Definition: qgsmarkersymbollayer.cpp:555
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:869
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:2396
QgsFontMarkerSymbolLayer::clone
QgsFontMarkerSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
Definition: qgsmarkersymbollayer.cpp:3356
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:225
QgsSimpleMarkerSymbolLayer::setStrokeWidthUnit
void setStrokeWidthUnit(QgsUnitTypes::RenderUnit u)
Sets the unit for the width of the marker's stroke.
Definition: qgsmarkersymbollayer.h:337
QgsSimpleMarkerSymbolLayer::mSelBrush
QBrush mSelBrush
QBrush to use as fill of selected symbols.
Definition: qgsmarkersymbollayer.h:402
QgsSvgMarkerSymbolLayer::resolvePaths
static void resolvePaths(QgsStringMap &properties, const QgsPathResolver &pathResolver, bool saving)
Turns relative paths in properties map to absolute when reading and vice versa when writing.
Definition: qgsmarkersymbollayer.cpp:1895
QgsSvgMarkerSymbolLayer::setStrokeWidthUnit
void setStrokeWidthUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the stroke width.
Definition: qgsmarkersymbollayer.h:588
QgsSymbolLayer::PropertyFontStyle
@ PropertyFontStyle
Font style.
Definition: qgssymbollayer.h:190
QgsMarkerSymbolLayer::mOffsetUnit
QgsUnitTypes::RenderUnit mOffsetUnit
Offset units.
Definition: qgssymbollayer.h:871
QgsFilledMarkerSymbolLayer::stopRender
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
Definition: qgsmarkersymbollayer.cpp:1611
QgsSymbolRenderContext::selected
bool selected() const
Returns true if symbols should be rendered using the selected symbol coloring and style.
Definition: qgssymbol.h:764
QgsSymbolLayerUtils::createDisplacementElement
static void createDisplacementElement(QDomDocument &doc, QDomElement &element, QPointF offset)
Definition: qgssymbollayerutils.cpp:2520
qt_defaultDpiY
Q_GUI_EXPORT int qt_defaultDpiY()
QgsMarkerSymbolLayer::mSize
double mSize
Marker size.
Definition: qgssymbollayer.h:863
QgsUnitTypes::decodeRenderUnit
static Q_INVOKABLE QgsUnitTypes::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
Definition: qgsunittypes.cpp:2900
QgsSymbolRenderContext
Definition: qgssymbol.h:681
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:759
QgsSimpleMarkerSymbolLayer::color
QColor color() const override
The fill color.
Definition: qgsmarkersymbollayer.cpp:1528
QgsFontMarkerSymbolLayer::stopRender
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
Definition: qgsmarkersymbollayer.cpp:3115
QgsMarkerSymbolLayer::HorizontalAnchorPoint
HorizontalAnchorPoint
Symbol horizontal anchor points.
Definition: qgssymbollayer.h:580
QgsSvgMarkerSymbolLayer::strokeWidth
double strokeWidth() const
Definition: qgsmarkersymbollayer.h:580
QgsMarkerSymbolLayer::setOutputUnit
void setOutputUnit(QgsUnitTypes::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
Definition: qgssymbollayer.cpp:606
QgsSvgMarkerSymbolLayer::updateDefaultAspectRatio
double updateDefaultAspectRatio()
Calculates the default marker aspect ratio between width and height.
Definition: qgsmarkersymbollayer.cpp:1953
QgsSymbolLayerUtils::toPoint
static QPointF toPoint(const QVariant &value, bool *ok=nullptr)
Converts a value to a point.
Definition: qgssymbollayerutils.cpp:443
QgsFontMarkerSymbolLayer::setStrokeWidthUnit
void setStrokeWidthUnit(QgsUnitTypes::RenderUnit unit)
Sets the stroke width unit.
Definition: qgsmarkersymbollayer.h:929
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:1477
QgsSvgMarkerSymbolLayer::setStrokeColor
void setStrokeColor(const QColor &c) override
Set stroke color.
Definition: qgsmarkersymbollayer.h:578
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:473
QgsSimpleMarkerSymbolLayerBase
Abstract base class for simple marker symbol layers. Handles creation of the symbol shapes but leaves...
Definition: qgsmarkersymbollayer.h:43
QgsSvgMarkerSymbolLayer::strokeColor
QColor strokeColor() const override
Gets stroke color.
Definition: qgsmarkersymbollayer.h:577
QgsSimpleMarkerSymbolLayer::mBrush
QBrush mBrush
QBrush corresponding to marker's fill style.
Definition: qgsmarkersymbollayer.h:395
DEFAULT_SVGMARKER_ANGLE
#define DEFAULT_SVGMARKER_ANGLE
Definition: qgsmarkersymbollayer.h:476
QgsSimpleMarkerSymbolLayerBase::mShape
Shape mShape
Symbol shape.
Definition: qgsmarkersymbollayer.h:178
QgsSymbolLayer::PropertyOffset
@ PropertyOffset
Symbol offset.
Definition: qgssymbollayer.h:139
QgsSymbolLayer::PropertyCharacter
@ PropertyCharacter
Character, eg for font marker symbol layers.
Definition: qgssymbollayer.h:140
QgsSymbolLayer
Definition: qgssymbollayer.h:52
QgsRenderContext::forceVectorOutput
bool forceVectorOutput() const
Returns true if rendering operations should use vector operations instead of any faster raster shortc...
Definition: qgsrendercontext.cpp:215
QgsSimpleMarkerSymbolLayerBase::Shape
Shape
Marker symbol shapes.
Definition: qgsmarkersymbollayer.h:48
QgsDxfExport::mapUnits
QgsUnitTypes::DistanceUnit mapUnits() const
Retrieve map units.
Definition: qgsdxfexport.cpp:245
QgsDxfPaintDevice
Definition: qgsdxfpaintdevice.h:37
QgsSimpleMarkerSymbolLayer::fillColor
QColor fillColor() const override
Gets fill color.
Definition: qgsmarkersymbollayer.h:251
QgsRasterMarkerSymbolLayer::setMapUnitScale
void setMapUnitScale(const QgsMapUnitScale &scale) override
Definition: qgsmarkersymbollayer.cpp:2945
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:2297
QgsSimpleMarkerSymbolLayer::MAXIMUM_CACHE_WIDTH
static const int MAXIMUM_CACHE_WIDTH
Maximum width/height of cache image.
Definition: qgsmarkersymbollayer.h:412
QgsSvgMarkerSymbolLayer::startRender
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
Definition: qgsmarkersymbollayer.cpp:1988
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:736
QgsSimpleMarkerSymbolLayerBase::RightHalfTriangle
@ RightHalfTriangle
Right half of triangle.
Definition: qgsmarkersymbollayer.h:71
QgsSvgMarkerSymbolLayer::mStrokeWidthMapUnitScale
QgsMapUnitScale mStrokeWidthMapUnitScale
Definition: qgsmarkersymbollayer.h:630
QgsSymbolRenderContext::fields
QgsFields fields() const
Fields of the layer.
Definition: qgssymbol.h:814
QgsRasterMarkerSymbolLayer::layerType
QString layerType() const override
Returns a string that represents this layer type.
Definition: qgsmarkersymbollayer.cpp:2700
QgsDxfPaintDevice::setLayer
void setLayer(const QString &layer)
Definition: qgsdxfpaintdevice.cpp:90
QgsSimpleMarkerSymbolLayerBase::DiagonalHalfSquare
@ DiagonalHalfSquare
Diagonal half square (bottom left half)
Definition: qgsmarkersymbollayer.h:70
QgsSvgMarkerSymbolLayer::fillColor
QColor fillColor() const override
Gets fill color.
Definition: qgsmarkersymbollayer.h:574
QgsImageCache::pathAsImage
QImage pathAsImage(const QString &path, const QSize size, const bool keepAspectRatio, const double opacity, bool &fitsInCache, bool blocking=false, bool *isMissing=nullptr)
Returns the specified path rendered as an image.
Definition: qgsimagecache.cpp:104
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)
Calculates the viewbox size of a (possibly cached) SVG file.
Definition: qgssvgcache.cpp:216
QgsSimpleMarkerSymbolLayerBase::Star
@ Star
Star.
Definition: qgsmarkersymbollayer.h:56
QgsRenderContext::RenderBlocking
@ RenderBlocking
Render and load remote sources in the same thread to ensure rendering remote sources (svg and images)...
Definition: qgsrendercontext.h:81
QgsSvgMarkerSymbolLayer::setStrokeWidth
void setStrokeWidth(double w)
Definition: qgsmarkersymbollayer.h:581
QgsFontMarkerSymbolLayer::createFromSld
static QgsSymbolLayer * createFromSld(QDomElement &element)
Creates a new QgsFontMarkerSymbolLayer from an SLD XML element.
Definition: qgsmarkersymbollayer.cpp:3444
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:315
QgsSimpleMarkerSymbolLayerBase::Pentagon
@ Pentagon
Pentagon.
Definition: qgsmarkersymbollayer.h:52
QgsFontMarkerSymbolLayer::layerType
QString layerType() const override
Returns a string that represents this layer type.
Definition: qgsmarkersymbollayer.cpp:3063
QgsMapToPixel::mapRotation
double mapRotation() const
Returns current map rotation in degrees.
Definition: qgsmaptopixel.cpp:158
QgsSvgMarkerSymbolLayer::setPreservedAspectRatio
bool setPreservedAspectRatio(bool par)
Set preserved the marker aspect ratio between width and height.
Definition: qgsmarkersymbollayer.cpp:1968
QgsSvgMarkerSymbolLayer::path
QString path() const
Returns the marker SVG path.
Definition: qgsmarkersymbollayer.h:523
QgsSimpleMarkerSymbolLayerBase::ArrowHeadFilled
@ ArrowHeadFilled
Right facing filled arrow head.
Definition: qgsmarkersymbollayer.h:64
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:432
DEFAULT_FONTMARKER_SIZE
#define DEFAULT_FONTMARKER_SIZE
Definition: qgsmarkersymbollayer.h:790
QgsSimpleMarkerSymbolLayerBase::LeftHalfTriangle
@ LeftHalfTriangle
Left half of triangle.
Definition: qgsmarkersymbollayer.h:72
QgsSymbolLayerUtils::rescaleUom
static double rescaleUom(double size, QgsUnitTypes::RenderUnit unit, const QgsStringMap &props)
Rescales the given size based on the uomScale found in the props, if any is found,...
Definition: qgssymbollayerutils.cpp:4262
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:1255
QgsSimpleMarkerSymbolLayer
Simple marker symbol layer, consisting of a rendered shape with solid fill color and an stroke.
Definition: qgsmarkersymbollayer.h:198
QgsSimpleMarkerSymbolLayerBase::mPolygon
QPolygonF mPolygon
Polygon of points in shape. If polygon is empty then shape is using mPath.
Definition: qgsmarkersymbollayer.h:172
DEFAULT_FONTMARKER_CHR
#define DEFAULT_FONTMARKER_CHR
Definition: qgsmarkersymbollayer.h:789
QgsFilledMarkerSymbolLayer::subSymbol
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
Definition: qgsmarkersymbollayer.cpp:1650
QgsSvgMarkerSymbolLayer::mStrokeWidth
double mStrokeWidth
Definition: qgsmarkersymbollayer.h:628
QgsSvgMarkerSymbolLayer
Definition: qgsmarkersymbollayer.h:482
QgsSymbolLayer::PropertySize
@ PropertySize
Symbol size.
Definition: qgssymbollayer.h:132
QgsSymbolLayer::copyPaintEffect
void copyPaintEffect(QgsSymbolLayer *destLayer) const
Copies paint effect of this layer to another symbol layer.
Definition: qgssymbollayer.cpp:406
QgsSymbolLayerUtils::decodePoint
static QPointF decodePoint(const QString &string)
Decodes a QSizeF from a string.
Definition: qgssymbollayerutils.cpp:435
QgsSymbolLayer::PropertyStrokeStyle
@ PropertyStrokeStyle
Stroke style (eg solid, dashed)
Definition: qgssymbollayer.h:138
QgsMarkerSymbolLayer::outputUnit
QgsUnitTypes::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
Definition: qgssymbollayer.cpp:612
QgsRasterMarkerSymbolLayer::resolvePaths
static void resolvePaths(QgsStringMap &properties, const QgsPathResolver &pathResolver, bool saving)
Turns relative paths in properties map to absolute when reading and vice versa when writing.
Definition: qgsmarkersymbollayer.cpp:2658
QgsFilledMarkerSymbolLayer::layerType
QString layerType() const override
Returns a string that represents this layer type.
Definition: qgsmarkersymbollayer.cpp:1596
QgsApplication::imageCache
static QgsImageCache * imageCache()
Returns the application's image cache, used for caching resampled versions of raster images.
Definition: qgsapplication.cpp:2134
QgsRasterMarkerSymbolLayer::calculateAspectRatio
double calculateAspectRatio(QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedAspectRatio) const
Calculates the marker aspect ratio between width and height.
Definition: qgsmarkersymbollayer.cpp:2834
qgsrendercontext.h
QgsRasterMarkerSymbolLayer::setPath
void setPath(const QString &path)
Set the marker raster image path.
Definition: qgsmarkersymbollayer.cpp:2670
QgsSimpleMarkerSymbolLayerBase::Circle
@ Circle
Circle.
Definition: qgsmarkersymbollayer.h:58
DEFAULT_SIMPLEMARKER_BORDERCOLOR
#define DEFAULT_SIMPLEMARKER_BORDERCOLOR
Definition: qgsmarkersymbollayer.h:25
QgsSimpleMarkerSymbolLayerBase::shapeIsFilled
static bool shapeIsFilled(QgsSimpleMarkerSymbolLayerBase::Shape shape)
Returns true if a symbol shape has a fill.
Definition: qgsmarkersymbollayer.cpp:100
DEFAULT_FONTMARKER_BORDERCOLOR
#define DEFAULT_FONTMARKER_BORDERCOLOR
Definition: qgsmarkersymbollayer.h:792
QgsSvgMarkerSymbolLayer::create
static QgsSymbolLayer * create(const QgsStringMap &properties=QgsStringMap())
Definition: qgsmarkersymbollayer.cpp:1760
QgsSimpleMarkerSymbolLayer::prepareCache
bool prepareCache(QgsSymbolRenderContext &context)
Prepares cache image.
Definition: qgsmarkersymbollayer.cpp:878
QgsSimpleMarkerSymbolLayer::strokeWidth
double strokeWidth() const
Returns the width of the marker's stroke.
Definition: qgsmarkersymbollayer.h:319
QgsSimpleMarkerSymbolLayer::startRender
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
Definition: qgsmarkersymbollayer.cpp:816
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:1440
QgsFontMarkerSymbolLayer::setPenJoinStyle
void setPenJoinStyle(Qt::PenJoinStyle style)
Sets the stroke join style.
Definition: qgsmarkersymbollayer.h:969
QgsRasterMarkerSymbolLayer
Raster marker symbol layer class.
Definition: qgsmarkersymbollayer.h:650
QgsSimpleMarkerSymbolLayer::mStrokeColor
QColor mStrokeColor
Stroke color.
Definition: qgsmarkersymbollayer.h:381
QgsSvgMarkerSymbolLayer::renderPoint
void renderPoint(QPointF point, QgsSymbolRenderContext &context) override
Renders a marker at the specified point.
Definition: qgsmarkersymbollayer.cpp:1999
QgsSvgMarkerSymbolLayer::mStrokeWidthUnit
QgsUnitTypes::RenderUnit mStrokeWidthUnit
Definition: qgsmarkersymbollayer.h:629
QgsSymbolLayer::PropertyName
@ PropertyName
Name, eg shape name for simple markers.
Definition: qgssymbollayer.h:134
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:712
QgsRasterMarkerSymbolLayer::mPath
QString mPath
Definition: qgsmarkersymbollayer.h:768
QgsSymbol::Fill
@ Fill
Fill symbol.
Definition: qgssymbol.h:89
QgsSimpleMarkerSymbolLayerBase::ThirdCircle
@ ThirdCircle
One third circle (top left third)
Definition: qgsmarkersymbollayer.h:66
QgsSvgMarkerSymbolLayer::clone
QgsSvgMarkerSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
Definition: qgsmarkersymbollayer.cpp:2270
QgsMapUnitScale
Struct for storing maximum and minimum scales for measurements in map units.
Definition: qgsmapunitscale.h:37
QgsSimpleMarkerSymbolLayerBase::CrossFill
@ CrossFill
Solid filled cross.
Definition: qgsmarkersymbollayer.h:60
QgsSvgMarkerSymbolLayer::properties
QgsStringMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
Definition: qgsmarkersymbollayer.cpp:2247
QgsImageOperation::adjustHueSaturation
static void adjustHueSaturation(QImage &image, double saturation, const QColor &colorizeColor=QColor(), double colorizeStrength=1.0)
Alter the hue or saturation of a QImage.
Definition: qgsimageoperation.cpp:268
QgsSimpleMarkerSymbolLayer::setStrokeWidth
void setStrokeWidth(double w)
Sets the width of the marker's stroke.
Definition: qgsmarkersymbollayer.h:328
QgsSymbolLayer::mDataDefinedProperties
QgsPropertyCollection mDataDefinedProperties
Definition: qgssymbollayer.h:524
QgsSymbolLayer::PropertyStrokeWidth
@ PropertyStrokeWidth
Stroke width.
Definition: qgssymbollayer.h:137
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:266
QgsRingSequence
QVector< QgsPointSequence > QgsRingSequence
Definition: qgsabstractgeometry.h:48
QgsRasterMarkerSymbolLayer::path
QString path() const
Returns the marker raster image path.
Definition: qgsmarkersymbollayer.h:696
QgsMarkerSymbolLayer::setOffsetUnit
void setOffsetUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the symbol's offset.
Definition: qgssymbollayer.h:730
QgsSimpleMarkerSymbolLayerBase::decodeShape
static QgsSimpleMarkerSymbolLayerBase::Shape decodeShape(const QString &name, bool *ok=nullptr)
Attempts to decode a string representation of a shape name to the corresponding shape.
Definition: qgsmarkersymbollayer.cpp:292
QgsSimpleMarkerSymbolLayer::mStrokeStyle
Qt::PenStyle mStrokeStyle
Stroke style.
Definition: qgsmarkersymbollayer.h:383
QgsSymbolLayerUtils::encodePoint
static QString encodePoint(QPointF point)
Encodes a QPointF to a string.
Definition: qgssymbollayerutils.cpp:430
QgsApplication::svgCache
static QgsSvgCache * svgCache()
Returns the application's SVG cache, used for caching SVG images and handling parameter replacement w...
Definition: qgsapplication.cpp:2129
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:246
QgsRasterMarkerSymbolLayer::QgsRasterMarkerSymbolLayer
QgsRasterMarkerSymbolLayer(const QString &path=QString(), double size=DEFAULT_SVGMARKER_SIZE, double angle=DEFAULT_SVGMARKER_ANGLE, QgsSymbol::ScaleMethod scaleMethod=DEFAULT_SCALE_METHOD)
Constructs raster marker symbol layer with picture from given absolute path to a raster image file.
Definition: qgsmarkersymbollayer.cpp:2595
QgsFontMarkerSymbolLayer::writeSldMarker
void writeSldMarker(QDomDocument &doc, QDomElement &element, const QgsStringMap &props) const override
Writes the symbol layer definition as a SLD XML element.
Definition: qgsmarkersymbollayer.cpp:3377
DEG2RAD
#define DEG2RAD(x)
Definition: qgsdistancearea.cpp:40
QgsSvgMarkerSymbolLayer::setStrokeWidthMapUnitScale
void setStrokeWidthMapUnitScale(const QgsMapUnitScale &scale)
Definition: qgsmarkersymbollayer.h:596
QgsSimpleMarkerSymbolLayer::strokeColor
QColor strokeColor() const override
Returns the marker's stroke color.
Definition: qgsmarkersymbollayer.h:264
QgsSymbolRenderContext::renderHints
QgsSymbol::RenderHints renderHints() const
Returns the rendering hint flags for the symbol.
Definition: qgssymbol.h:776
QgsSvgMarkerSymbolLayer::writeSldMarker
void writeSldMarker(QDomDocument &doc, QDomElement &element, const QgsStringMap &props) const override
Writes the symbol layer definition as a SLD XML element.
Definition: qgsmarkersymbollayer.cpp:2322
QgsSimpleMarkerSymbolLayerBase::Square
@ Square
Square.
Definition: qgsmarkersymbollayer.h:50
QgsSimpleMarkerSymbolLayer::mSelPen
QPen mSelPen
QPen to use as stroke of selected symbols.
Definition: qgsmarkersymbollayer.h:400
QgsSimpleMarkerSymbolLayer::mapUnitScale
QgsMapUnitScale mapUnitScale() const override
Definition: qgsmarkersymbollayer.cpp:1468
QgsRenderContext::selectionColor
QColor selectionColor() const
Returns the color to use when rendering selected features.
Definition: qgsrendercontext.h:374
QgsSimpleMarkerSymbolLayer::createFromSld
static QgsSymbolLayer * createFromSld(QDomElement &element)
Creates a new QgsSimpleMarkerSymbolLayer from an SLD XML element.
Definition: qgsmarkersymbollayer.cpp:1194
QgsSvgMarkerSymbolLayer::calculateAspectRatio
double calculateAspectRatio(QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedAspectRatio) const
Calculates the marker aspect ratio between width and height.
Definition: qgsmarkersymbollayer.cpp:2167
QgsSimpleMarkerSymbolLayer::writeSldMarker
void writeSldMarker(QDomDocument &doc, QDomElement &element, const QgsStringMap &props) const override
Writes the symbol layer definition as a SLD XML element.
Definition: qgsmarkersymbollayer.cpp:1103
QgsMarkerSymbolLayer::setOffsetMapUnitScale
void setOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the symbol's offset.
Definition: qgssymbollayer.h:747
QgsStringMap
QMap< QString, QString > QgsStringMap
Definition: qgis.h:714
QgsSimpleMarkerSymbolLayer::setMapUnitScale
void setMapUnitScale(const QgsMapUnitScale &scale) override
Definition: qgsmarkersymbollayer.cpp:1462
QgsMarkerSymbolLayer::mOffset
QPointF mOffset
Marker offset.
Definition: qgssymbollayer.h:869
QgsWkbTypes::PointGeometry
@ PointGeometry
Definition: qgswkbtypes.h:141
QgsFontMarkerSymbolLayer::create
static QgsSymbolLayer * create(const QgsStringMap &properties=QgsStringMap())
Creates a new QgsFontMarkerSymbolLayer from a property map (see properties())
Definition: qgsmarkersymbollayer.cpp:3009
QgsFontMarkerSymbolLayer::fontStyle
QString fontStyle() const
Returns the font style for the associated font which will be used to render the point.
Definition: qgsmarkersymbollayer.h:861
QgsSimpleMarkerSymbolLayerBase::renderPoint
void renderPoint(QPointF point, QgsSymbolRenderContext &context) override
Renders a marker at the specified point.
Definition: qgsmarkersymbollayer.cpp:182
QgsFilledMarkerSymbolLayer::setSubSymbol
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
Definition: qgsmarkersymbollayer.cpp:1655
QgsMarkerSymbolLayer::mHorizontalAnchorPoint
HorizontalAnchorPoint mHorizontalAnchorPoint
Horizontal anchor point.
Definition: qgssymbollayer.h:877
QgsSvgMarkerSymbolLayer::stopRender
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
Definition: qgsmarkersymbollayer.cpp:1994
QgsSvgMarkerSymbolLayer::setFillColor
void setFillColor(const QColor &color) override
Set fill color.
Definition: qgsmarkersymbollayer.h:575
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:572
QgsFilledMarkerSymbolLayer::clone
QgsFilledMarkerSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
Definition: qgsmarkersymbollayer.cpp:1641
QgsSimpleMarkerSymbolLayerBase::QuarterCircle
@ QuarterCircle
Quarter circle (top left quarter)
Definition: qgsmarkersymbollayer.h:67
QgsPointSequence
QVector< QgsPoint > QgsPointSequence
Definition: qgsabstractgeometry.h:44
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:218
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:175
QgsMapToPixel
Definition: qgsmaptopixel.h:37
QgsDxfExport::writeFilledCircle
void writeFilledCircle(const QString &layer, const QColor &color, const QgsPoint &pt, double radius)
Write filled circle (as hatch)
Definition: qgsdxfexport.cpp:1403
QgsSimpleMarkerSymbolLayerBase::Cross2
@ Cross2
Rotated cross (lines only), "x" shape.
Definition: qgsmarkersymbollayer.h:61
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:1686
DEFAULT_SVGMARKER_SIZE
#define DEFAULT_SVGMARKER_SIZE
Definition: qgsmarkersymbollayer.h:475
QgsSimpleMarkerSymbolLayer::setStrokeColor
void setStrokeColor(const QColor &color) override
Sets the marker's stroke color.
Definition: qgsmarkersymbollayer.h:273
QgsFeature::hasGeometry
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:197
QgsSymbol::DynamicRotation
@ DynamicRotation
Rotation of symbol may be changed during rendering and symbol should not be cached.
Definition: qgssymbol.h:106
qgsimagecache.h
QgsSimpleMarkerSymbolLayer::mStrokeWidthUnit
QgsUnitTypes::RenderUnit mStrokeWidthUnit
Stroke width units.
Definition: qgsmarkersymbollayer.h:387
QgsSimpleMarkerSymbolLayer::layerType
QString layerType() const override
Returns a string that represents this layer type.
Definition: qgsmarkersymbollayer.cpp:811
QgsSimpleMarkerSymbolLayerBase::Cross
@ Cross
Cross (lines only)
Definition: qgsmarkersymbollayer.h:59
QgsSymbolLayerUtils::svgSymbolNameToPath
static QString svgSymbolNameToPath(const QString &name, const QgsPathResolver &pathResolver)
Determines an SVG symbol's path from its name.
Definition: qgssymbollayerutils.cpp:3879
QgsMarkerSymbolLayer::mLineAngle
double mLineAngle
Line rotation angle (see setLineAngle() for details)
Definition: qgssymbollayer.h:861
QgsFontMarkerSymbolLayer
Definition: qgsmarkersymbollayer.h:800
DEFAULT_SCALE_METHOD
#define DEFAULT_SCALE_METHOD
Definition: qgssymbollayer.h:19
QgsFontMarkerSymbolLayer::renderPoint
void renderPoint(QPointF point, QgsSymbolRenderContext &context) override
Renders a marker at the specified point.
Definition: qgsmarkersymbollayer.cpp:3215
QgsSymbolLayerUtils::rotationFromSldElement
static bool rotationFromSldElement(QDomElement &element, QString &rotationFunc)
Definition: qgssymbollayerutils.cpp:2489
QgsSymbolLayerUtils::encodeScaleMethod
static QString encodeScaleMethod(QgsSymbol::ScaleMethod scaleMethod)
Definition: qgssymbollayerutils.cpp:713
QgsSymbolLayer::PropertyAngle
@ PropertyAngle
Symbol angle.
Definition: qgssymbollayer.h:133
QgsFillSymbol
Definition: qgssymbol.h:1212
QgsUnitTypes::RenderMetersInMapUnits
@ RenderMetersInMapUnits
Meters value as Map units.
Definition: qgsunittypes.h:175
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:549
QgsRenderContext::pathResolver
const QgsPathResolver & pathResolver() const
Returns the path resolver for conversion between relative and absolute paths during rendering operati...
Definition: qgsrendercontext.h:264
QgsUnitTypes::RenderUnknownUnit
@ RenderUnknownUnit
Mixed or unknown units.
Definition: qgsunittypes.h:174
QgsSymbol::type
SymbolType type() const
Returns the symbol's type.
Definition: qgssymbol.h:122
QgsSymbolLayer::restoreOldDataDefinedProperties
void restoreOldDataDefinedProperties(const QgsStringMap &stringMap)
Restores older data defined properties from string map.
Definition: qgssymbollayer.cpp:277
QgsRasterMarkerSymbolLayer::mOpacity
double mOpacity
The marker default opacity.
Definition: qgsmarkersymbollayer.h:770
QgsSymbolLayerUtils::decodePenJoinStyle
static Qt::PenJoinStyle decodePenJoinStyle(const QString &str)
Definition: qgssymbollayerutils.cpp:188
QgsSimpleMarkerSymbolLayer::mUsingCache
bool mUsingCache
true if using cached images of markers for drawing.
Definition: qgsmarkersymbollayer.h:410
QgsRenderContext::Antialiasing
@ Antialiasing
Use antialiasing while drawing.
Definition: qgsrendercontext.h:78
QgsSimpleMarkerSymbolLayerBase::availableShapes
static QList< QgsSimpleMarkerSymbolLayerBase::Shape > availableShapes()
Returns a list of all available shape types.
Definition: qgsmarkersymbollayer.cpp:60
QgsSymbolLayerUtils::createRotationElement
static void createRotationElement(QDomDocument &doc, QDomElement &element, const QString &rotationFunc)
Definition: qgssymbollayerutils.cpp:2479
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)
Gets SVG as QPicture&.
Definition: qgssvgcache.cpp:182
QgsMarkerSymbolLayer::_rotatedOffset
static QPointF _rotatedOffset(QPointF offset, double angle)
Adjusts a marker offset to account for rotation.
Definition: qgssymbollayer.cpp:567
QgsMarkerSymbolLayer::offset
QPointF offset() const
Returns the marker's offset, which is the horizontal and vertical displacement which the rendered mar...
Definition: qgssymbollayer.h:721
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:681
QgsMarkerSymbolLayer::setVerticalAnchorPoint
void setVerticalAnchorPoint(VerticalAnchorPoint v)
Sets the vertical anchor point for positioning the symbol.
Definition: qgssymbollayer.h:781
QgsSvgMarkerSymbolLayer::QgsSvgMarkerSymbolLayer
QgsSvgMarkerSymbolLayer(const QString &path, double size=DEFAULT_SVGMARKER_SIZE, double angle=DEFAULT_SVGMARKER_ANGLE, QgsSymbol::ScaleMethod scaleMethod=DEFAULT_SCALE_METHOD)
Constructs SVG marker symbol layer with picture from given absolute path to a SVG file.
Definition: qgsmarkersymbollayer.cpp:1745
qgsdxfexport.h
QgsSimpleMarkerSymbolLayer::mCache
QImage mCache
Cached image of marker, if using cached version.
Definition: qgsmarkersymbollayer.h:398
QgsSimpleMarkerSymbolLayerBase::calculateOffsetAndRotation
void calculateOffsetAndRotation(QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedRotation, QPointF &offset, double &angle) const
Calculates the marker offset and rotation.
Definition: qgsmarkersymbollayer.cpp:654
DEFAULT_FONTMARKER_JOINSTYLE
#define DEFAULT_FONTMARKER_JOINSTYLE
Definition: qgsmarkersymbollayer.h:793
QgsMarkerSymbolLayer::mAngle
double mAngle
Marker rotation angle, in degrees clockwise from north.
Definition: qgssymbollayer.h:859
QgsRenderContext::RenderSymbolPreview
@ RenderSymbolPreview
The render is for a symbol preview only and map based properties may not be available,...
Definition: qgsrendercontext.h:82
QgsSymbolLayerUtils::encodePenJoinStyle
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
Definition: qgssymbollayerutils.cpp:173
QgsFeature
Definition: qgsfeature.h:55
QgsFillSymbol::createSimple
static QgsFillSymbol * createSimple(const QgsStringMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties.
Definition: qgssymbol.cpp:1440
QgsSymbolLayer::PropertyOpacity
@ PropertyOpacity
Opacity.
Definition: qgssymbollayer.h:167
QgsSvgMarkerSymbolLayer::mPath
QString mPath
Definition: qgsmarkersymbollayer.h:619
QgsFilledMarkerSymbolLayer::QgsFilledMarkerSymbolLayer
QgsFilledMarkerSymbolLayer(QgsSimpleMarkerSymbolLayerBase::Shape shape=Circle, double size=DEFAULT_SIMPLEMARKER_SIZE, double angle=DEFAULT_SIMPLEMARKER_ANGLE, QgsSymbol::ScaleMethod scaleMethod=DEFAULT_SCALE_METHOD)
Constructor for QgsFilledMarkerSymbolLayer.
Definition: qgsmarkersymbollayer.cpp:1547
QgsSymbolRenderContext::renderContext
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
Definition: qgssymbol.h:708
QgsSimpleMarkerSymbolLayer::QgsSimpleMarkerSymbolLayer
QgsSimpleMarkerSymbolLayer(QgsSimpleMarkerSymbolLayerBase::Shape shape=Circle, double size=DEFAULT_SIMPLEMARKER_SIZE, double angle=DEFAULT_SIMPLEMARKER_ANGLE, QgsSymbol::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:707
QgsDxfExport::symbologyScale
double symbologyScale() const
Returns the reference scale for output.
Definition: qgsdxfexport.h:227
QgsSymbolLayerUtils::estimateMaxSymbolBleed
static double estimateMaxSymbolBleed(QgsSymbol *symbol, const QgsRenderContext &context)
Returns the maximum estimated bleed for the symbol.
Definition: qgssymbollayerutils.cpp:820
QgsFontMarkerSymbolLayer::setStrokeWidthMapUnitScale
void setStrokeWidthMapUnitScale(const QgsMapUnitScale &scale)
Sets the stroke width map unit scale.
Definition: qgsmarkersymbollayer.h:951
QgsDxfPaintDevice::setShift
void setShift(QPointF shift)
Definition: qgsdxfpaintdevice.cpp:98
QgsDxfExport::clipValueToMapUnitScale
void clipValueToMapUnitScale(double &value, const QgsMapUnitScale &scale, double pixelToMMFactor) const
Clips value to scale minimum/maximum.
Definition: qgsdxfexport.cpp:1836
QgsSymbolLayer::PropertyHeight
@ PropertyHeight
Symbol height.
Definition: qgssymbollayer.h:142
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:2234
qgslogger.h
QgsSimpleMarkerSymbolLayerBase::HalfSquare
@ HalfSquare
Half square (left half)
Definition: qgsmarkersymbollayer.h:69
QgsRenderContext::painter
QPainter * painter()
Returns the destination QPainter for the render operation.
Definition: qgsrendercontext.h:174
QgsSimpleMarkerSymbolLayer::outputUnit
QgsUnitTypes::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
Definition: qgsmarkersymbollayer.cpp:1453
QgsSymbol::ScaleArea
@ ScaleArea
Calculate scale by the area.
Definition: qgssymbol.h:98
DEFAULT_FONTMARKER_COLOR
#define DEFAULT_FONTMARKER_COLOR
Definition: qgsmarkersymbollayer.h:791
QgsSymbolLayerUtils::decodePenStyle
static Qt::PenStyle decodePenStyle(const QString &str)
Definition: qgssymbollayerutils.cpp:162
DEFAULT_SIMPLEMARKER_COLOR
#define DEFAULT_SIMPLEMARKER_COLOR
Definition: qgsmarkersymbollayer.h:24
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, bool *isMissingImage=nullptr)
Gets SVG content.
Definition: qgssvgcache.cpp:206
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:2397
QgsRasterMarkerSymbolLayer::mDefaultAspectRatio
double mDefaultAspectRatio
The marker default aspect ratio.
Definition: qgsmarkersymbollayer.h:772
QgsSymbolLayerUtils::displacementFromSldElement
static bool displacementFromSldElement(QDomElement &element, QPointF &offset)
Definition: qgssymbollayerutils.cpp:2555
QgsPropertyCollection::isActive
bool isActive(int key) const override
Returns true if the collection contains an active property with the specified key.
Definition: qgspropertycollection.cpp:258
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:2322
QgsGeometry::type
QgsWkbTypes::GeometryType type
Definition: qgsgeometry.h:126
QgsSimpleMarkerSymbolLayerBase::encodeShape
static QString encodeShape(QgsSimpleMarkerSymbolLayerBase::Shape shape)
Encodes a shape to its string representation.
Definition: qgsmarkersymbollayer.cpp:350
QgsSimpleMarkerSymbolLayerBase::EquilateralTriangle
@ EquilateralTriangle
Equilateral triangle.
Definition: qgsmarkersymbollayer.h:55
QgsMarkerSymbolLayer::mOffsetMapUnitScale
QgsMapUnitScale mOffsetMapUnitScale
Offset map unit scale.
Definition: qgssymbollayer.h:873
QgsSimpleMarkerSymbolLayerBase::shapeToPolygon
bool shapeToPolygon(Shape shape, QPolygonF &polygon) const
Creates a polygon representing the specified shape.
Definition: qgsmarkersymbollayer.cpp:409
QgsSimpleMarkerSymbolLayerBase::QgsSimpleMarkerSymbolLayerBase
QgsSimpleMarkerSymbolLayerBase(QgsSimpleMarkerSymbolLayerBase::Shape shape=Circle, double size=DEFAULT_SIMPLEMARKER_SIZE, double angle=DEFAULT_SIMPLEMARKER_ANGLE, QgsSymbol::ScaleMethod scaleMethod=DEFAULT_SCALE_METHOD)
Constructor for QgsSimpleMarkerSymbolLayerBase.
Definition: qgsmarkersymbollayer.cpp:89
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:398
QgsFontMarkerSymbolLayer::startRender
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
Definition: qgsmarkersymbollayer.cpp:3068
QgsPathResolver
Definition: qgspathresolver.h:31
QgsUnitTypes::RenderMapUnits
@ RenderMapUnits
Map units.
Definition: qgsunittypes.h:169
QgsSimpleMarkerSymbolLayerBase::shape
QgsSimpleMarkerSymbolLayerBase::Shape shape() const
Returns the shape for the rendered marker symbol.
Definition: qgsmarkersymbollayer.h:101
QgsSymbolLayerUtils::decodeMapUnitScale
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
Definition: qgssymbollayerutils.cpp:568
QgsMarkerSymbolLayer::angle
double angle() const
Returns the rotation angle for the marker, in degrees clockwise from north.
Definition: qgssymbollayer.h:627
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:846
QgsSvgMarkerSymbolLayer::mFixedAspectRatio
double mFixedAspectRatio
The marker fixed aspect ratio.
Definition: qgsmarkersymbollayer.h:624
QgsRasterMarkerSymbolLayer::create
static QgsSymbolLayer * create(const QgsStringMap &properties=QgsStringMap())
Creates a raster marker symbol layer from a string map of properties.
Definition: qgsmarkersymbollayer.cpp:2606
QgsSimpleMarkerSymbolLayerBase::calculateSize
double calculateSize(QgsSymbolRenderContext &context, bool &hasDataDefinedSize) const
Calculates the desired size of the marker, considering data defined size overrides.
Definition: qgsmarkersymbollayer.cpp:626
QgsSimpleMarkerSymbolLayerBase::ArrowHead
@ ArrowHead
Right facing arrow head (unfilled, lines only)
Definition: qgsmarkersymbollayer.h:63
QgsRasterMarkerSymbolLayer::setPreservedAspectRatio
bool setPreservedAspectRatio(bool par)
Set preserved the marker aspect ratio between width and height.
Definition: qgsmarkersymbollayer.cpp:2676
QgsSimpleMarkerSymbolLayer::mPen
QPen mPen
QPen corresponding to marker's stroke style.
Definition: qgsmarkersymbollayer.h:393
QgsSimpleMarkerSymbolLayer::setFillColor
void setFillColor(const QColor &color) override
Set fill color.
Definition: qgsmarkersymbollayer.h:252
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:897
QgsSvgMarkerSymbolLayer::mStrokeColor
QColor mStrokeColor
Definition: qgsmarkersymbollayer.h:627
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:937
QgsSymbolLayer::PropertyJoinStyle
@ PropertyJoinStyle
Line join style.
Definition: qgssymbollayer.h:145
QgsSimpleMarkerSymbolLayer::drawMarker
void drawMarker(QPainter *p, QgsSymbolRenderContext &context)
Draws the marker shape in the specified painter.
Definition: qgsmarkersymbollayer.cpp:1241
QgsRenderContext::flags
Flags flags() const
Returns combination of flags used for rendering.
Definition: qgsrendercontext.cpp:160
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:3407
QgsSimpleMarkerSymbolLayerBase::stopRender
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
Definition: qgsmarkersymbollayer.cpp:177
QgsSymbolLayer::PropertyWidth
@ PropertyWidth
Symbol width.
Definition: qgssymbollayer.h:141
QgsSimpleMarkerSymbolLayerBase::Diamond
@ Diamond
Diamond.
Definition: qgsmarkersymbollayer.h:51
DEFAULT_RASTERMARKER_ANGLE
#define DEFAULT_RASTERMARKER_ANGLE
Definition: qgsmarkersymbollayer.h:642
QgsSimpleMarkerSymbolLayer::mStrokeWidthMapUnitScale
QgsMapUnitScale mStrokeWidthMapUnitScale
Stroke width map unit scale.
Definition: qgsmarkersymbollayer.h:389
DEFAULT_SIMPLEMARKER_SIZE
#define DEFAULT_SIMPLEMARKER_SIZE
Definition: qgsmarkersymbollayer.h:27
QgsSimpleMarkerSymbolLayer::mStrokeWidth
double mStrokeWidth
Stroke width.
Definition: qgsmarkersymbollayer.h:385