QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
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  {
250  transform.rotate( angle );
251  }
252 
253  //need to pass: symbol, polygon, path
254 
255  QPolygonF polygon;
256  QPainterPath path;
257  if ( !mPolygon.isEmpty() )
258  {
259  polygon = transform.map( mPolygon );
260  }
261  else
262  {
263  path = transform.map( mPath );
264  }
265  draw( context, symbol, polygon, path );
266 }
267 
269 {
270  bool hasDataDefinedSize = false;
271  double scaledSize = calculateSize( context, hasDataDefinedSize );
272 
273  bool hasDataDefinedRotation = false;
274  QPointF offset;
275  double angle = 0;
276  calculateOffsetAndRotation( context, scaledSize, hasDataDefinedRotation, offset, angle );
277 
278  scaledSize = context.renderContext().convertToPainterUnits( scaledSize, mSizeUnit, mSizeMapUnitScale );
279 
280  QTransform transform;
281 
282  // move to the desired position
283  transform.translate( point.x() + offset.x(), point.y() + offset.y() );
284 
285  if ( !qgsDoubleNear( angle, 0.0 ) )
286  transform.rotate( angle );
287 
288  return transform.mapRect( QRectF( -scaledSize / 2.0,
289  -scaledSize / 2.0,
290  scaledSize,
291  scaledSize ) );
292 }
293 
295 {
296  if ( ok )
297  *ok = true;
298  QString cleaned = name.toLower().trimmed();
299 
300  if ( cleaned == QLatin1String( "square" ) || cleaned == QLatin1String( "rectangle" ) )
301  return Square;
302  else if ( cleaned == QLatin1String( "diamond" ) )
303  return Diamond;
304  else if ( cleaned == QLatin1String( "pentagon" ) )
305  return Pentagon;
306  else if ( cleaned == QLatin1String( "hexagon" ) )
307  return Hexagon;
308  else if ( cleaned == QLatin1String( "triangle" ) )
309  return Triangle;
310  else if ( cleaned == QLatin1String( "equilateral_triangle" ) )
311  return EquilateralTriangle;
312  else if ( cleaned == QLatin1String( "star" ) || cleaned == QLatin1String( "regular_star" ) )
313  return Star;
314  else if ( cleaned == QLatin1String( "arrow" ) )
315  return Arrow;
316  else if ( cleaned == QLatin1String( "circle" ) )
317  return Circle;
318  else if ( cleaned == QLatin1String( "cross" ) )
319  return Cross;
320  else if ( cleaned == QLatin1String( "cross_fill" ) )
321  return CrossFill;
322  else if ( cleaned == QLatin1String( "cross2" ) || cleaned == QLatin1String( "x" ) )
323  return Cross2;
324  else if ( cleaned == QLatin1String( "line" ) )
325  return Line;
326  else if ( cleaned == QLatin1String( "arrowhead" ) )
327  return ArrowHead;
328  else if ( cleaned == QLatin1String( "filled_arrowhead" ) )
329  return ArrowHeadFilled;
330  else if ( cleaned == QLatin1String( "semi_circle" ) )
331  return SemiCircle;
332  else if ( cleaned == QLatin1String( "third_circle" ) )
333  return ThirdCircle;
334  else if ( cleaned == QLatin1String( "quarter_circle" ) )
335  return QuarterCircle;
336  else if ( cleaned == QLatin1String( "quarter_square" ) )
337  return QuarterSquare;
338  else if ( cleaned == QLatin1String( "half_square" ) )
339  return HalfSquare;
340  else if ( cleaned == QLatin1String( "diagonal_half_square" ) )
341  return DiagonalHalfSquare;
342  else if ( cleaned == QLatin1String( "right_half_triangle" ) )
343  return RightHalfTriangle;
344  else if ( cleaned == QLatin1String( "left_half_triangle" ) )
345  return LeftHalfTriangle;
346 
347  if ( ok )
348  *ok = false;
349  return Circle;
350 }
351 
353 {
354  switch ( shape )
355  {
356  case Square:
357  return QStringLiteral( "square" );
358  case QuarterSquare:
359  return QStringLiteral( "quarter_square" );
360  case HalfSquare:
361  return QStringLiteral( "half_square" );
362  case DiagonalHalfSquare:
363  return QStringLiteral( "diagonal_half_square" );
364  case Diamond:
365  return QStringLiteral( "diamond" );
366  case Pentagon:
367  return QStringLiteral( "pentagon" );
368  case Hexagon:
369  return QStringLiteral( "hexagon" );
370  case Triangle:
371  return QStringLiteral( "triangle" );
372  case EquilateralTriangle:
373  return QStringLiteral( "equilateral_triangle" );
374  case LeftHalfTriangle:
375  return QStringLiteral( "left_half_triangle" );
376  case RightHalfTriangle:
377  return QStringLiteral( "right_half_triangle" );
378  case Star:
379  return QStringLiteral( "star" );
380  case Arrow:
381  return QStringLiteral( "arrow" );
382  case ArrowHeadFilled:
383  return QStringLiteral( "filled_arrowhead" );
384  case CrossFill:
385  return QStringLiteral( "cross_fill" );
386  case Circle:
387  return QStringLiteral( "circle" );
388  case Cross:
389  return QStringLiteral( "cross" );
390  case Cross2:
391  return QStringLiteral( "cross2" );
392  case Line:
393  return QStringLiteral( "line" );
394  case ArrowHead:
395  return QStringLiteral( "arrowhead" );
396  case SemiCircle:
397  return QStringLiteral( "semi_circle" );
398  case ThirdCircle:
399  return QStringLiteral( "third_circle" );
400  case QuarterCircle:
401  return QStringLiteral( "quarter_circle" );
402  }
403  return QString();
404 }
405 
407 {
408  return shapeToPolygon( shape, mPolygon );
409 }
410 
412 {
413  polygon.clear();
414 
415  switch ( shape )
416  {
417  case Square:
418  polygon = QPolygonF( QRectF( QPointF( -1, -1 ), QPointF( 1, 1 ) ) );
419  return true;
420 
421  case QuarterSquare:
422  polygon = QPolygonF( QRectF( QPointF( -1, -1 ), QPointF( 0, 0 ) ) );
423  return true;
424 
425  case HalfSquare:
426  polygon = QPolygonF( QRectF( QPointF( -1, -1 ), QPointF( 0, 1 ) ) );
427  return true;
428 
429  case DiagonalHalfSquare:
430  polygon << QPointF( -1, -1 ) << QPointF( 1, 1 ) << QPointF( -1, 1 ) << QPointF( -1, -1 );
431  return true;
432 
433  case Diamond:
434  polygon << QPointF( -1, 0 ) << QPointF( 0, 1 )
435  << QPointF( 1, 0 ) << QPointF( 0, -1 ) << QPointF( -1, 0 );
436  return true;
437 
438  case Pentagon:
439  /* angular-representation of hardcoded values used
440  polygon << QPointF( std::sin( DEG2RAD( 288.0 ) ), - std::cos( DEG2RAD( 288.0 ) ) )
441  << QPointF( std::sin( DEG2RAD( 216.0 ) ), - std::cos( DEG2RAD( 216.0 ) ) )
442  << QPointF( std::sin( DEG2RAD( 144.0 ) ), - std::cos( DEG2RAD( 144.0 ) ) )
443  << QPointF( std::sin( DEG2RAD( 72.0 ) ), - std::cos( DEG2RAD( 72.0 ) ) )
444  << QPointF( 0, -1 ); */
445  polygon << QPointF( -0.9511, -0.3090 )
446  << QPointF( -0.5878, 0.8090 )
447  << QPointF( 0.5878, 0.8090 )
448  << QPointF( 0.9511, -0.3090 )
449  << QPointF( 0, -1 )
450  << QPointF( -0.9511, -0.3090 );
451  return true;
452 
453  case Hexagon:
454  /* angular-representation of hardcoded values used
455  polygon << QPointF( std::sin( DEG2RAD( 300.0 ) ), - std::cos( DEG2RAD( 300.0 ) ) )
456  << QPointF( std::sin( DEG2RAD( 240.0 ) ), - std::cos( DEG2RAD( 240.0 ) ) )
457  << QPointF( std::sin( DEG2RAD( 180.0 ) ), - std::cos( DEG2RAD( 180.0 ) ) )
458  << QPointF( std::sin( DEG2RAD( 120.0 ) ), - std::cos( DEG2RAD( 120.0 ) ) )
459  << QPointF( std::sin( DEG2RAD( 60.0 ) ), - std::cos( DEG2RAD( 60.0 ) ) )
460  << QPointF( 0, -1 ); */
461  polygon << QPointF( -0.8660, -0.5 )
462  << QPointF( -0.8660, 0.5 )
463  << QPointF( 0, 1 )
464  << QPointF( 0.8660, 0.5 )
465  << QPointF( 0.8660, -0.5 )
466  << QPointF( 0, -1 )
467  << QPointF( -0.8660, -0.5 );
468  return true;
469 
470  case Triangle:
471  polygon << QPointF( -1, 1 ) << QPointF( 1, 1 ) << QPointF( 0, -1 ) << QPointF( -1, 1 );
472  return true;
473 
474  case EquilateralTriangle:
475  /* angular-representation of hardcoded values used
476  polygon << QPointF( std::sin( DEG2RAD( 240.0 ) ), - std::cos( DEG2RAD( 240.0 ) ) )
477  << QPointF( std::sin( DEG2RAD( 120.0 ) ), - std::cos( DEG2RAD( 120.0 ) ) )
478  << QPointF( 0, -1 ); */
479  polygon << QPointF( -0.8660, 0.5 )
480  << QPointF( 0.8660, 0.5 )
481  << QPointF( 0, -1 )
482  << QPointF( -0.8660, 0.5 );
483  return true;
484 
485  case LeftHalfTriangle:
486  polygon << QPointF( 0, 1 ) << QPointF( 1, 1 ) << QPointF( 0, -1 ) << QPointF( 0, 1 );
487  return true;
488 
489  case RightHalfTriangle:
490  polygon << QPointF( -1, 1 ) << QPointF( 0, 1 ) << QPointF( 0, -1 ) << QPointF( -1, 1 );
491  return true;
492 
493  case Star:
494  {
495  double inner_r = std::cos( DEG2RAD( 72.0 ) ) / std::cos( DEG2RAD( 36.0 ) );
496 
497  polygon << QPointF( inner_r * std::sin( DEG2RAD( 324.0 ) ), - inner_r * std::cos( DEG2RAD( 324.0 ) ) ) // 324
498  << QPointF( std::sin( DEG2RAD( 288.0 ) ), - std::cos( DEG2RAD( 288 ) ) ) // 288
499  << QPointF( inner_r * std::sin( DEG2RAD( 252.0 ) ), - inner_r * std::cos( DEG2RAD( 252.0 ) ) ) // 252
500  << QPointF( std::sin( DEG2RAD( 216.0 ) ), - std::cos( DEG2RAD( 216.0 ) ) ) // 216
501  << QPointF( 0, inner_r ) // 180
502  << QPointF( std::sin( DEG2RAD( 144.0 ) ), - std::cos( DEG2RAD( 144.0 ) ) ) // 144
503  << QPointF( inner_r * std::sin( DEG2RAD( 108.0 ) ), - inner_r * std::cos( DEG2RAD( 108.0 ) ) ) // 108
504  << QPointF( std::sin( DEG2RAD( 72.0 ) ), - std::cos( DEG2RAD( 72.0 ) ) ) // 72
505  << QPointF( inner_r * std::sin( DEG2RAD( 36.0 ) ), - inner_r * std::cos( DEG2RAD( 36.0 ) ) ) // 36
506  << QPointF( 0, -1 )
507  << QPointF( inner_r * std::sin( DEG2RAD( 324.0 ) ), - inner_r * std::cos( DEG2RAD( 324.0 ) ) ); // 324; // 0
508  return true;
509  }
510 
511  case Arrow:
512  polygon << QPointF( 0, -1 )
513  << QPointF( 0.5, -0.5 )
514  << QPointF( 0.25, -0.5 )
515  << QPointF( 0.25, 1 )
516  << QPointF( -0.25, 1 )
517  << QPointF( -0.25, -0.5 )
518  << QPointF( -0.5, -0.5 )
519  << QPointF( 0, -1 );
520  return true;
521 
522  case ArrowHeadFilled:
523  polygon << QPointF( 0, 0 ) << QPointF( -1, 1 ) << QPointF( -1, -1 ) << QPointF( 0, 0 );
524  return true;
525 
526  case CrossFill:
527  polygon << QPointF( -1, -0.2 )
528  << QPointF( -1, -0.2 )
529  << QPointF( -1, 0.2 )
530  << QPointF( -0.2, 0.2 )
531  << QPointF( -0.2, 1 )
532  << QPointF( 0.2, 1 )
533  << QPointF( 0.2, 0.2 )
534  << QPointF( 1, 0.2 )
535  << QPointF( 1, -0.2 )
536  << QPointF( 0.2, -0.2 )
537  << QPointF( 0.2, -1 )
538  << QPointF( -0.2, -1 )
539  << QPointF( -0.2, -0.2 )
540  << QPointF( -1, -0.2 );
541  return true;
542 
543  case Circle:
544  case Cross:
545  case Cross2:
546  case Line:
547  case ArrowHead:
548  case SemiCircle:
549  case ThirdCircle:
550  case QuarterCircle:
551  return false;
552  }
553 
554  return false;
555 }
556 
558 {
559  mPath = QPainterPath();
560 
561  switch ( symbol )
562  {
563  case Circle:
564 
565  mPath.addEllipse( QRectF( -1, -1, 2, 2 ) ); // x,y,w,h
566  return true;
567 
568  case SemiCircle:
569  mPath.arcTo( -1, -1, 2, 2, 0, 180 );
570  mPath.lineTo( 0, 0 );
571  return true;
572 
573  case ThirdCircle:
574  mPath.arcTo( -1, -1, 2, 2, 90, 120 );
575  mPath.lineTo( 0, 0 );
576  return true;
577 
578  case QuarterCircle:
579  mPath.arcTo( -1, -1, 2, 2, 90, 90 );
580  mPath.lineTo( 0, 0 );
581  return true;
582 
583  case Cross:
584  mPath.moveTo( -1, 0 );
585  mPath.lineTo( 1, 0 ); // horizontal
586  mPath.moveTo( 0, -1 );
587  mPath.lineTo( 0, 1 ); // vertical
588  return true;
589 
590  case Cross2:
591  mPath.moveTo( -1, -1 );
592  mPath.lineTo( 1, 1 );
593  mPath.moveTo( 1, -1 );
594  mPath.lineTo( -1, 1 );
595  return true;
596 
597  case Line:
598  mPath.moveTo( 0, -1 );
599  mPath.lineTo( 0, 1 ); // vertical line
600  return true;
601 
602  case ArrowHead:
603  mPath.moveTo( -1, -1 );
604  mPath.lineTo( 0, 0 );
605  mPath.lineTo( -1, 1 );
606  return true;
607 
608  case Square:
609  case QuarterSquare:
610  case HalfSquare:
611  case DiagonalHalfSquare:
612  case Diamond:
613  case Pentagon:
614  case Hexagon:
615  case Triangle:
616  case EquilateralTriangle:
617  case LeftHalfTriangle:
618  case RightHalfTriangle:
619  case Star:
620  case Arrow:
621  case ArrowHeadFilled:
622  case CrossFill:
623  return false;
624  }
625  return false;
626 }
627 
628 double QgsSimpleMarkerSymbolLayerBase::calculateSize( QgsSymbolRenderContext &context, bool &hasDataDefinedSize ) const
629 {
630  double scaledSize = mSize;
631 
633  bool ok = true;
634  if ( hasDataDefinedSize )
635  {
636  context.setOriginalValueVariable( mSize );
638  mSize, &ok );
639  }
640 
641  if ( hasDataDefinedSize && ok )
642  {
643  switch ( mScaleMethod )
644  {
646  scaledSize = std::sqrt( scaledSize );
647  break;
649  break;
650  }
651  }
652 
653  return scaledSize;
654 }
655 
656 void QgsSimpleMarkerSymbolLayerBase::calculateOffsetAndRotation( QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedRotation, QPointF &offset, double &angle ) const
657 {
658  //offset
659  double offsetX = 0;
660  double offsetY = 0;
661  markerOffset( context, scaledSize, scaledSize, offsetX, offsetY );
662  offset = QPointF( offsetX, offsetY );
663 
664  hasDataDefinedRotation = false;
665  //angle
666  bool ok = true;
667  angle = mAngle + mLineAngle;
669  {
670  context.setOriginalValueVariable( angle );
672 
673  // If the expression evaluation was not successful, fallback to static value
674  if ( !ok )
675  angle = mAngle + mLineAngle;
676 
677  hasDataDefinedRotation = true;
678  }
679 
680  hasDataDefinedRotation = context.renderHints() & QgsSymbol::DynamicRotation || hasDataDefinedRotation;
681 
682  if ( hasDataDefinedRotation )
683  {
684  // For non-point markers, "dataDefinedRotation" means following the
685  // shape (shape-data defined). For them, "field-data defined" does
686  // not work at all. TODO: if "field-data defined" ever gets implemented
687  // we'll need a way to distinguish here between the two, possibly
688  // using another flag in renderHints()
689  const QgsFeature *f = context.feature();
690  if ( f )
691  {
692  if ( f->hasGeometry() && f->geometry().type() == QgsWkbTypes::PointGeometry )
693  {
694  const QgsMapToPixel &m2p = context.renderContext().mapToPixel();
695  angle += m2p.mapRotation();
696  }
697  }
698  }
699 
700  if ( angle )
702 }
703 
704 
705 //
706 // QgsSimpleMarkerSymbolLayer
707 //
708 
709 QgsSimpleMarkerSymbolLayer::QgsSimpleMarkerSymbolLayer( QgsSimpleMarkerSymbolLayerBase::Shape shape, double size, double angle, QgsSymbol::ScaleMethod scaleMethod, const QColor &color, const QColor &strokeColor, Qt::PenJoinStyle penJoinStyle )
710  : QgsSimpleMarkerSymbolLayerBase( shape, size, angle, scaleMethod )
711  , mStrokeColor( strokeColor )
712  , mPenJoinStyle( penJoinStyle )
713 {
714  mColor = color;
715 }
716 
718 {
719  Shape shape = Circle;
722  Qt::PenJoinStyle penJoinStyle = DEFAULT_SIMPLEMARKER_JOINSTYLE;
726 
727  if ( props.contains( QStringLiteral( "name" ) ) )
728  {
729  shape = decodeShape( props[QStringLiteral( "name" )] );
730  }
731  if ( props.contains( QStringLiteral( "color" ) ) )
732  color = QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "color" )] );
733  if ( props.contains( QStringLiteral( "color_border" ) ) )
734  {
735  //pre 2.5 projects use "color_border"
736  strokeColor = QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "color_border" )] );
737  }
738  else if ( props.contains( QStringLiteral( "outline_color" ) ) )
739  {
740  strokeColor = QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "outline_color" )] );
741  }
742  else if ( props.contains( QStringLiteral( "line_color" ) ) )
743  {
744  strokeColor = QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "line_color" )] );
745  }
746  if ( props.contains( QStringLiteral( "joinstyle" ) ) )
747  {
748  penJoinStyle = QgsSymbolLayerUtils::decodePenJoinStyle( props[QStringLiteral( "joinstyle" )] );
749  }
750  if ( props.contains( QStringLiteral( "size" ) ) )
751  size = props[QStringLiteral( "size" )].toDouble();
752  if ( props.contains( QStringLiteral( "angle" ) ) )
753  angle = props[QStringLiteral( "angle" )].toDouble();
754  if ( props.contains( QStringLiteral( "scale_method" ) ) )
755  scaleMethod = QgsSymbolLayerUtils::decodeScaleMethod( props[QStringLiteral( "scale_method" )] );
756 
758  if ( props.contains( QStringLiteral( "offset" ) ) )
759  m->setOffset( QgsSymbolLayerUtils::decodePoint( props[QStringLiteral( "offset" )] ) );
760  if ( props.contains( QStringLiteral( "offset_unit" ) ) )
761  m->setOffsetUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "offset_unit" )] ) );
762  if ( props.contains( QStringLiteral( "offset_map_unit_scale" ) ) )
763  m->setOffsetMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "offset_map_unit_scale" )] ) );
764  if ( props.contains( QStringLiteral( "size_unit" ) ) )
765  m->setSizeUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "size_unit" )] ) );
766  if ( props.contains( QStringLiteral( "size_map_unit_scale" ) ) )
767  m->setSizeMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "size_map_unit_scale" )] ) );
768 
769  if ( props.contains( QStringLiteral( "outline_style" ) ) )
770  {
771  m->setStrokeStyle( QgsSymbolLayerUtils::decodePenStyle( props[QStringLiteral( "outline_style" )] ) );
772  }
773  else if ( props.contains( QStringLiteral( "line_style" ) ) )
774  {
775  m->setStrokeStyle( QgsSymbolLayerUtils::decodePenStyle( props[QStringLiteral( "line_style" )] ) );
776  }
777  if ( props.contains( QStringLiteral( "outline_width" ) ) )
778  {
779  m->setStrokeWidth( props[QStringLiteral( "outline_width" )].toDouble() );
780  }
781  else if ( props.contains( QStringLiteral( "line_width" ) ) )
782  {
783  m->setStrokeWidth( props[QStringLiteral( "line_width" )].toDouble() );
784  }
785  if ( props.contains( QStringLiteral( "outline_width_unit" ) ) )
786  {
787  m->setStrokeWidthUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "outline_width_unit" )] ) );
788  }
789  if ( props.contains( QStringLiteral( "line_width_unit" ) ) )
790  {
791  m->setStrokeWidthUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "line_width_unit" )] ) );
792  }
793  if ( props.contains( QStringLiteral( "outline_width_map_unit_scale" ) ) )
794  {
795  m->setStrokeWidthMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "outline_width_map_unit_scale" )] ) );
796  }
797 
798  if ( props.contains( QStringLiteral( "horizontal_anchor_point" ) ) )
799  {
800  m->setHorizontalAnchorPoint( QgsMarkerSymbolLayer::HorizontalAnchorPoint( props[ QStringLiteral( "horizontal_anchor_point" )].toInt() ) );
801  }
802  if ( props.contains( QStringLiteral( "vertical_anchor_point" ) ) )
803  {
804  m->setVerticalAnchorPoint( QgsMarkerSymbolLayer::VerticalAnchorPoint( props[ QStringLiteral( "vertical_anchor_point" )].toInt() ) );
805  }
806 
808 
809  return m;
810 }
811 
812 
814 {
815  return QStringLiteral( "SimpleMarker" );
816 }
817 
819 {
821 
822  QColor brushColor = mColor;
823  QColor penColor = mStrokeColor;
824 
825  brushColor.setAlphaF( mColor.alphaF() * context.opacity() );
826  penColor.setAlphaF( mStrokeColor.alphaF() * context.opacity() );
827 
828  mBrush = QBrush( brushColor );
829  mPen = QPen( penColor );
830  mPen.setStyle( mStrokeStyle );
831  mPen.setJoinStyle( mPenJoinStyle );
833 
834  QColor selBrushColor = context.renderContext().selectionColor();
835  QColor selPenColor = selBrushColor == mColor ? selBrushColor : mStrokeColor;
836  if ( context.opacity() < 1 && !SELECTION_IS_OPAQUE )
837  {
838  selBrushColor.setAlphaF( context.opacity() );
839  selPenColor.setAlphaF( context.opacity() );
840  }
841  mSelBrush = QBrush( selBrushColor );
842  mSelPen = QPen( selPenColor );
843  mSelPen.setStyle( mStrokeStyle );
845 
847  bool hasDataDefinedSize = mDataDefinedProperties.isActive( QgsSymbolLayer::PropertySize );
848 
849  // use caching only when:
850  // - size, rotation, shape, color, stroke color is not data-defined
851  // - drawing to screen (not printer)
852  mUsingCache = !hasDataDefinedRotation && !hasDataDefinedSize && !context.renderContext().forceVectorOutput()
856 
857  if ( !shapeIsFilled( mShape ) )
858  {
859  // some markers can't be drawn as a polygon (circle, cross)
860  // For these set the selected stroke color to the selected color
861  mSelPen.setColor( selBrushColor );
862  }
863 
864 
865  if ( mUsingCache )
866  {
867  if ( !prepareCache( context ) )
868  {
869  mUsingCache = false;
870  }
871  }
872  else
873  {
874  mCache = QImage();
875  mSelCache = QImage();
876  }
877 }
878 
879 
881 {
882  double scaledSize = context.renderContext().convertToPainterUnits( mSize, mSizeUnit, mSizeMapUnitScale );
884  {
885  // rendering for symbol previews -- a size in meters in map units can't be calculated, so treat the size as millimeters
886  // and clamp it to a reasonable range. It's the best we can do in this situation!
887  scaledSize = std::min( std::max( context.renderContext().convertToPainterUnits( mSize, QgsUnitTypes::RenderMillimeters ), 3.0 ), 100.0 );
888  }
889 
890  // take into account angle (which is not data-defined otherwise cache wouldn't be used)
891  if ( !qgsDoubleNear( mAngle, 0.0 ) )
892  {
893  scaledSize = ( std::abs( std::sin( mAngle * M_PI / 180 ) ) + std::abs( std::cos( mAngle * M_PI / 180 ) ) ) * scaledSize;
894  }
895  // calculate necessary image size for the cache
896  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
897  int imageSize = ( static_cast< int >( scaledSize ) + pw ) / 2 * 2 + 1; // make image width, height odd; account for pen width
898  double center = imageSize / 2.0;
899  if ( imageSize > MAXIMUM_CACHE_WIDTH )
900  {
901  return false;
902  }
903 
904  mCache = QImage( QSize( imageSize, imageSize ), QImage::Format_ARGB32_Premultiplied );
905  mCache.fill( 0 );
906 
907  bool needsBrush = shapeIsFilled( mShape );
908 
909  QPainter p;
910  p.begin( &mCache );
911  p.setRenderHint( QPainter::Antialiasing );
912  p.setBrush( needsBrush ? mBrush : Qt::NoBrush );
913  p.setPen( mPen );
914  p.translate( QPointF( center, center ) );
915  drawMarker( &p, context );
916  p.end();
917 
918  // Construct the selected version of the Cache
919 
920  QColor selColor = context.renderContext().selectionColor();
921 
922  mSelCache = QImage( QSize( imageSize, imageSize ), QImage::Format_ARGB32_Premultiplied );
923  mSelCache.fill( 0 );
924 
925  p.begin( &mSelCache );
926  p.setRenderHint( QPainter::Antialiasing );
927  p.setBrush( needsBrush ? mSelBrush : Qt::NoBrush );
928  p.setPen( mSelPen );
929  p.translate( QPointF( center, center ) );
930  drawMarker( &p, context );
931  p.end();
932 
933  // Check that the selected version is different. If not, then re-render,
934  // filling the background with the selection color and using the normal
935  // colors for the symbol .. could be ugly!
936 
937  if ( mSelCache == mCache )
938  {
939  p.begin( &mSelCache );
940  p.setRenderHint( QPainter::Antialiasing );
941  p.fillRect( 0, 0, imageSize, imageSize, selColor );
942  p.setBrush( needsBrush ? mBrush : Qt::NoBrush );
943  p.setPen( mPen );
944  p.translate( QPointF( center, center ) );
945  drawMarker( &p, context );
946  p.end();
947  }
948 
949  return true;
950 }
951 
952 void QgsSimpleMarkerSymbolLayer::draw( QgsSymbolRenderContext &context, QgsSimpleMarkerSymbolLayerBase::Shape shape, const QPolygonF &polygon, const QPainterPath &path )
953 {
954  //making changes here? Don't forget to also update ::bounds if the changes affect the bounding box
955  //of the rendered point!
956 
957  QPainter *p = context.renderContext().painter();
958  if ( !p )
959  {
960  return;
961  }
962 
963  bool ok = true;
965  {
968  if ( ok )
969  mBrush.setColor( c );
970  }
972  {
975  if ( ok )
976  {
977  mPen.setColor( c );
978  mSelPen.setColor( c );
979  }
980  }
982  {
985  if ( ok )
986  {
989  }
990  }
992  {
995  if ( ok )
996  {
999  }
1000  }
1002  {
1005  if ( ok )
1006  {
1007  mPen.setJoinStyle( QgsSymbolLayerUtils::decodePenJoinStyle( style ) );
1008  mSelPen.setJoinStyle( QgsSymbolLayerUtils::decodePenJoinStyle( style ) );
1009  }
1010  }
1011 
1012  if ( shapeIsFilled( shape ) )
1013  {
1014  p->setBrush( context.selected() ? mSelBrush : mBrush );
1015  }
1016  else
1017  {
1018  p->setBrush( Qt::NoBrush );
1019  }
1020  p->setPen( context.selected() ? mSelPen : mPen );
1021 
1022  if ( !polygon.isEmpty() )
1023  p->drawPolygon( polygon );
1024  else
1025  p->drawPath( path );
1026 }
1027 
1029 {
1030  //making changes here? Don't forget to also update ::bounds if the changes affect the bounding box
1031  //of the rendered point!
1032 
1033  QPainter *p = context.renderContext().painter();
1034  if ( !p )
1035  {
1036  return;
1037  }
1038 
1039  if ( mUsingCache )
1040  {
1041  QImage &img = context.selected() ? mSelCache : mCache;
1042  double s = img.width();
1043 
1044  bool hasDataDefinedSize = false;
1045  double scaledSize = calculateSize( context, hasDataDefinedSize );
1046 
1047  bool hasDataDefinedRotation = false;
1048  QPointF offset;
1049  double angle = 0;
1050  calculateOffsetAndRotation( context, scaledSize, hasDataDefinedRotation, offset, angle );
1051 
1052  p->drawImage( QRectF( point.x() - s / 2.0 + offset.x(),
1053  point.y() - s / 2.0 + offset.y(),
1054  s, s ), img );
1055  }
1056  else
1057  {
1059  }
1060 }
1061 
1063 {
1064  QgsStringMap map;
1065  map[QStringLiteral( "name" )] = encodeShape( mShape );
1066  map[QStringLiteral( "color" )] = QgsSymbolLayerUtils::encodeColor( mColor );
1067  map[QStringLiteral( "outline_color" )] = QgsSymbolLayerUtils::encodeColor( mStrokeColor );
1068  map[QStringLiteral( "size" )] = QString::number( mSize );
1069  map[QStringLiteral( "size_unit" )] = QgsUnitTypes::encodeUnit( mSizeUnit );
1070  map[QStringLiteral( "size_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mSizeMapUnitScale );
1071  map[QStringLiteral( "angle" )] = QString::number( mAngle );
1072  map[QStringLiteral( "offset" )] = QgsSymbolLayerUtils::encodePoint( mOffset );
1073  map[QStringLiteral( "offset_unit" )] = QgsUnitTypes::encodeUnit( mOffsetUnit );
1074  map[QStringLiteral( "offset_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mOffsetMapUnitScale );
1075  map[QStringLiteral( "scale_method" )] = QgsSymbolLayerUtils::encodeScaleMethod( mScaleMethod );
1076  map[QStringLiteral( "outline_style" )] = QgsSymbolLayerUtils::encodePenStyle( mStrokeStyle );
1077  map[QStringLiteral( "outline_width" )] = QString::number( mStrokeWidth );
1078  map[QStringLiteral( "outline_width_unit" )] = QgsUnitTypes::encodeUnit( mStrokeWidthUnit );
1079  map[QStringLiteral( "outline_width_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mStrokeWidthMapUnitScale );
1080  map[QStringLiteral( "joinstyle" )] = QgsSymbolLayerUtils::encodePenJoinStyle( mPenJoinStyle );
1081  map[QStringLiteral( "horizontal_anchor_point" )] = QString::number( mHorizontalAnchorPoint );
1082  map[QStringLiteral( "vertical_anchor_point" )] = QString::number( mVerticalAnchorPoint );
1083  return map;
1084 }
1085 
1087 {
1089  m->setOffset( mOffset );
1090  m->setSizeUnit( mSizeUnit );
1092  m->setOffsetUnit( mOffsetUnit );
1101  copyPaintEffect( m );
1102  return m;
1103 }
1104 
1105 void QgsSimpleMarkerSymbolLayer::writeSldMarker( QDomDocument &doc, QDomElement &element, const QgsStringMap &props ) const
1106 {
1107  // <Graphic>
1108  QDomElement graphicElem = doc.createElement( QStringLiteral( "se:Graphic" ) );
1109  element.appendChild( graphicElem );
1110 
1114 
1115  // <Rotation>
1116  QString angleFunc;
1117  bool ok;
1118  double angle = props.value( QStringLiteral( "angle" ), QStringLiteral( "0" ) ).toDouble( &ok );
1119  if ( !ok )
1120  {
1121  angleFunc = QStringLiteral( "%1 + %2" ).arg( props.value( QStringLiteral( "angle" ), QStringLiteral( "0" ) ) ).arg( mAngle );
1122  }
1123  else if ( !qgsDoubleNear( angle + mAngle, 0.0 ) )
1124  {
1125  angleFunc = QString::number( angle + mAngle );
1126  }
1127  QgsSymbolLayerUtils::createRotationElement( doc, graphicElem, angleFunc );
1128 
1129  // <Displacement>
1132 }
1133 
1134 QString QgsSimpleMarkerSymbolLayer::ogrFeatureStyle( double mmScaleFactor, double mapUnitScaleFactor ) const
1135 {
1136  Q_UNUSED( mmScaleFactor )
1137  Q_UNUSED( mapUnitScaleFactor )
1138 #if 0
1139  QString ogrType = "3"; //default is circle
1140  if ( mName == "square" )
1141  {
1142  ogrType = "5";
1143  }
1144  else if ( mName == "triangle" )
1145  {
1146  ogrType = "7";
1147  }
1148  else if ( mName == "star" )
1149  {
1150  ogrType = "9";
1151  }
1152  else if ( mName == "circle" )
1153  {
1154  ogrType = "3";
1155  }
1156  else if ( mName == "cross" )
1157  {
1158  ogrType = "0";
1159  }
1160  else if ( mName == "x" || mName == "cross2" )
1161  {
1162  ogrType = "1";
1163  }
1164  else if ( mName == "line" )
1165  {
1166  ogrType = "10";
1167  }
1168 
1169  QString ogrString;
1170  ogrString.append( "SYMBOL(" );
1171  ogrString.append( "id:" );
1172  ogrString.append( '\"' );
1173  ogrString.append( "ogr-sym-" );
1174  ogrString.append( ogrType );
1175  ogrString.append( '\"' );
1176  ogrString.append( ",c:" );
1177  ogrString.append( mColor.name() );
1178  ogrString.append( ",o:" );
1179  ogrString.append( mStrokeColor.name() );
1180  ogrString.append( QString( ",s:%1mm" ).arg( mSize ) );
1181  ogrString.append( ')' );
1182  return ogrString;
1183 #endif //0
1184 
1185  QString ogrString;
1186  ogrString.append( "PEN(" );
1187  ogrString.append( "c:" );
1188  ogrString.append( mColor.name() );
1189  ogrString.append( ",w:" );
1190  ogrString.append( QString::number( mSize ) );
1191  ogrString.append( "mm" );
1192  ogrString.append( ")" );
1193  return ogrString;
1194 }
1195 
1197 {
1198  QgsDebugMsgLevel( QStringLiteral( "Entered." ), 4 );
1199 
1200  QDomElement graphicElem = element.firstChildElement( QStringLiteral( "Graphic" ) );
1201  if ( graphicElem.isNull() )
1202  return nullptr;
1203 
1204  QString name = QStringLiteral( "square" );
1205  QColor color, strokeColor;
1206  double strokeWidth, size;
1207  Qt::PenStyle strokeStyle;
1208 
1210  return nullptr;
1211 
1212  double angle = 0.0;
1213  QString angleFunc;
1214  if ( QgsSymbolLayerUtils::rotationFromSldElement( graphicElem, angleFunc ) )
1215  {
1216  bool ok;
1217  double d = angleFunc.toDouble( &ok );
1218  if ( ok )
1219  angle = d;
1220  }
1221 
1222  QPointF offset;
1224 
1225  Shape shape = decodeShape( name );
1226 
1227  QString uom = element.attribute( QStringLiteral( "uom" ) );
1231 
1233  m->setOutputUnit( QgsUnitTypes::RenderUnit::RenderPixels );
1234  m->setColor( color );
1236  m->setAngle( angle );
1237  m->setOffset( offset );
1240  return m;
1241 }
1242 
1244 {
1245  Q_UNUSED( context )
1246 
1247  if ( mPolygon.count() != 0 )
1248  {
1249  p->drawPolygon( mPolygon );
1250  }
1251  else
1252  {
1253  p->drawPath( mPath );
1254  }
1255 }
1256 
1257 bool QgsSimpleMarkerSymbolLayer::writeDxf( QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, QgsSymbolRenderContext &context, QPointF shift ) const
1258 {
1259  //data defined size?
1260  double size = mSize;
1261 
1262  bool hasDataDefinedSize = mDataDefinedProperties.isActive( QgsSymbolLayer::PropertySize );
1263 
1264  //data defined size
1265  bool ok = true;
1266  if ( hasDataDefinedSize )
1267  {
1269 
1270  if ( ok )
1271  {
1272  switch ( mScaleMethod )
1273  {
1274  case QgsSymbol::ScaleArea:
1275  size = std::sqrt( size );
1276  break;
1278  break;
1279  }
1280  }
1281 
1283  }
1284 
1286  {
1287  size *= mmMapUnitScaleFactor;
1288  }
1289 
1291  {
1293  }
1294  double halfSize = size / 2.0;
1295 
1296  //strokeWidth
1297  double strokeWidth = mStrokeWidth;
1298 
1300  {
1303  }
1306  {
1308  }
1309 
1310  //color
1311  QColor pc = mPen.color();
1312  QColor bc = mBrush.color();
1314  {
1317  }
1319  {
1322  }
1323 
1324  //offset
1325  double offsetX = 0;
1326  double offsetY = 0;
1327  markerOffset( context, offsetX, offsetY );
1328  offsetX *= context.renderContext().mapToPixel().mapUnitsPerPixel();
1329  offsetY *= context.renderContext().mapToPixel().mapUnitsPerPixel();
1330 
1331 
1332  QPointF off( offsetX, offsetY );
1333 
1334  //angle
1335  double angle = mAngle + mLineAngle;
1337  {
1338  context.setOriginalValueVariable( mAngle );
1340  }
1341 
1342  Shape shape = mShape;
1344  {
1346  QString shapeName = mDataDefinedProperties.valueAsString( QgsSymbolLayer::PropertyName, context.renderContext().expressionContext(), QString(), &ok );
1347  if ( ok )
1348  {
1349  shape = decodeShape( shapeName, &ok );
1350  if ( !ok )
1351  shape = mShape;
1352  }
1353  }
1354 
1355  if ( angle )
1356  off = _rotatedOffset( off, angle );
1357 
1359 
1360  QTransform t;
1361  t.translate( shift.x() + off.x(), shift.y() - off.y() );
1362 
1363  if ( !qgsDoubleNear( angle, 0.0 ) )
1364  t.rotate( angle );
1365 
1366  QPolygonF polygon;
1367  if ( shapeToPolygon( shape, polygon ) )
1368  {
1369  t.scale( halfSize, -halfSize );
1370 
1371  polygon = t.map( polygon );
1372 
1373  QgsPointSequence p;
1374  p.reserve( polygon.size() );
1375  for ( int i = 0; i < polygon.size(); i++ )
1376  {
1377  p << QgsPoint( polygon[i] );
1378  }
1379 
1380  if ( mBrush.style() != Qt::NoBrush )
1381  e.writePolygon( QgsRingSequence() << p, layerName, QStringLiteral( "SOLID" ), bc );
1382  if ( mPen.style() != Qt::NoPen )
1383  e.writePolyline( p, layerName, QStringLiteral( "CONTINUOUS" ), pc, strokeWidth );
1384  }
1385  else if ( shape == Circle )
1386  {
1387  shift += QPointF( off.x(), -off.y() );
1388  if ( mBrush.style() != Qt::NoBrush )
1389  e.writeFilledCircle( layerName, bc, QgsPoint( shift ), halfSize );
1390  if ( mPen.style() != Qt::NoPen )
1391  e.writeCircle( layerName, pc, QgsPoint( shift ), halfSize, QStringLiteral( "CONTINUOUS" ), strokeWidth );
1392  }
1393  else if ( shape == Line )
1394  {
1395  QPointF pt1 = t.map( QPointF( 0, -halfSize ) );
1396  QPointF pt2 = t.map( QPointF( 0, halfSize ) );
1397 
1398  if ( mPen.style() != Qt::NoPen )
1399  e.writeLine( QgsPoint( pt1 ), QgsPoint( pt2 ), layerName, QStringLiteral( "CONTINUOUS" ), pc, strokeWidth );
1400  }
1401  else if ( shape == Cross )
1402  {
1403  if ( mPen.style() != Qt::NoPen )
1404  {
1405  QPointF pt1 = t.map( QPointF( -halfSize, 0 ) );
1406  QPointF pt2 = t.map( QPointF( halfSize, 0 ) );
1407  QPointF pt3 = t.map( QPointF( 0, -halfSize ) );
1408  QPointF pt4 = t.map( QPointF( 0, halfSize ) );
1409 
1410  e.writeLine( QgsPoint( pt1 ), QgsPoint( pt2 ), layerName, QStringLiteral( "CONTINUOUS" ), pc, strokeWidth );
1411  e.writeLine( QgsPoint( pt3 ), QgsPoint( pt4 ), layerName, QStringLiteral( "CONTINUOUS" ), pc, strokeWidth );
1412  }
1413  }
1414  else if ( shape == Cross2 )
1415  {
1416  if ( mPen.style() != Qt::NoPen )
1417  {
1418  QPointF pt1 = t.map( QPointF( -halfSize, -halfSize ) );
1419  QPointF pt2 = t.map( QPointF( halfSize, halfSize ) );
1420  QPointF pt3 = t.map( QPointF( halfSize, -halfSize ) );
1421  QPointF pt4 = t.map( QPointF( -halfSize, halfSize ) );
1422 
1423  e.writeLine( QgsPoint( pt1 ), QgsPoint( pt2 ), layerName, QStringLiteral( "CONTINUOUS" ), pc, strokeWidth );
1424  e.writeLine( QgsPoint( pt3 ), QgsPoint( pt4 ), layerName, QStringLiteral( "CONTINUOUS" ), pc, strokeWidth );
1425  }
1426  }
1427  else if ( shape == ArrowHead )
1428  {
1429  if ( mPen.style() != Qt::NoPen )
1430  {
1431  QPointF pt1 = t.map( QPointF( -halfSize, halfSize ) );
1432  QPointF pt2 = t.map( QPointF( 0, 0 ) );
1433  QPointF pt3 = t.map( QPointF( -halfSize, -halfSize ) );
1434 
1435  e.writeLine( QgsPoint( pt1 ), QgsPoint( pt2 ), layerName, QStringLiteral( "CONTINUOUS" ), pc, strokeWidth );
1436  e.writeLine( QgsPoint( pt3 ), QgsPoint( pt2 ), layerName, QStringLiteral( "CONTINUOUS" ), pc, strokeWidth );
1437  }
1438  }
1439  else
1440  {
1441  QgsDebugMsg( QStringLiteral( "Unsupported dxf marker name %1" ).arg( encodeShape( shape ) ) );
1442  return false;
1443  }
1444 
1445  return true;
1446 }
1447 
1448 
1450 {
1452  mStrokeWidthUnit = unit;
1453 }
1454 
1456 {
1458  {
1459  return mStrokeWidthUnit;
1460  }
1462 }
1463 
1465 {
1467  mStrokeWidthMapUnitScale = scale;
1468 }
1469 
1471 {
1473  {
1474  return mStrokeWidthMapUnitScale;
1475  }
1476  return QgsMapUnitScale();
1477 }
1478 
1480 {
1481  QRectF symbolBounds = QgsSimpleMarkerSymbolLayerBase::bounds( point, context );
1482 
1483  // need to account for stroke width
1484  double penWidth = mStrokeWidth;
1485  bool ok = true;
1487  {
1490  if ( ok )
1491  {
1492  penWidth = strokeWidth;
1493  }
1494  }
1497  {
1500  if ( ok && strokeStyle == QLatin1String( "no" ) )
1501  {
1502  penWidth = 0.0;
1503  }
1504  }
1505  else if ( mStrokeStyle == Qt::NoPen )
1506  penWidth = 0;
1507 
1508  //antialiasing, add 1 pixel
1509  penWidth += 1;
1510 
1511  //extend bounds by pen width / 2.0
1512  symbolBounds.adjust( -penWidth / 2.0, -penWidth / 2.0,
1513  penWidth / 2.0, penWidth / 2.0 );
1514 
1515  return symbolBounds;
1516 }
1517 
1518 void QgsSimpleMarkerSymbolLayer::setColor( const QColor &color )
1519 {
1520  if ( shapeIsFilled( mShape ) )
1521  {
1522  setFillColor( color );
1523  }
1524  else
1525  {
1526  setStrokeColor( color );
1527  }
1528 }
1529 
1531 {
1532  if ( shapeIsFilled( mShape ) )
1533  {
1534  return fillColor();
1535  }
1536  else
1537  {
1538  return strokeColor();
1539  }
1540 }
1541 
1542 
1543 
1544 
1545 //
1546 // QgsFilledMarkerSymbolLayer
1547 //
1548 
1550  : QgsSimpleMarkerSymbolLayerBase( shape, size, angle, scaleMethod )
1551 {
1552  mFill.reset( static_cast<QgsFillSymbol *>( QgsFillSymbol::createSimple( QgsStringMap() ) ) );
1553 }
1554 
1556 {
1557  QString name = DEFAULT_SIMPLEMARKER_NAME;
1561 
1562  if ( props.contains( QStringLiteral( "name" ) ) )
1563  name = props[QStringLiteral( "name" )];
1564  if ( props.contains( QStringLiteral( "size" ) ) )
1565  size = props[QStringLiteral( "size" )].toDouble();
1566  if ( props.contains( QStringLiteral( "angle" ) ) )
1567  angle = props[QStringLiteral( "angle" )].toDouble();
1568  if ( props.contains( QStringLiteral( "scale_method" ) ) )
1569  scaleMethod = QgsSymbolLayerUtils::decodeScaleMethod( props[QStringLiteral( "scale_method" )] );
1570 
1572  if ( props.contains( QStringLiteral( "offset" ) ) )
1573  m->setOffset( QgsSymbolLayerUtils::decodePoint( props[QStringLiteral( "offset" )] ) );
1574  if ( props.contains( QStringLiteral( "offset_unit" ) ) )
1575  m->setOffsetUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "offset_unit" )] ) );
1576  if ( props.contains( QStringLiteral( "offset_map_unit_scale" ) ) )
1577  m->setOffsetMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "offset_map_unit_scale" )] ) );
1578  if ( props.contains( QStringLiteral( "size_unit" ) ) )
1579  m->setSizeUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "size_unit" )] ) );
1580  if ( props.contains( QStringLiteral( "size_map_unit_scale" ) ) )
1581  m->setSizeMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "size_map_unit_scale" )] ) );
1582  if ( props.contains( QStringLiteral( "horizontal_anchor_point" ) ) )
1583  {
1584  m->setHorizontalAnchorPoint( QgsMarkerSymbolLayer::HorizontalAnchorPoint( props[ QStringLiteral( "horizontal_anchor_point" )].toInt() ) );
1585  }
1586  if ( props.contains( QStringLiteral( "vertical_anchor_point" ) ) )
1587  {
1588  m->setVerticalAnchorPoint( QgsMarkerSymbolLayer::VerticalAnchorPoint( props[ QStringLiteral( "vertical_anchor_point" )].toInt() ) );
1589  }
1590 
1592 
1593  m->restoreOldDataDefinedProperties( props );
1594 
1595  return m;
1596 }
1597 
1599 {
1600  return QStringLiteral( "FilledMarker" );
1601 }
1602 
1604 {
1605  if ( mFill )
1606  {
1607  mFill->startRender( context.renderContext(), context.fields() );
1608  }
1609 
1611 }
1612 
1614 {
1615  if ( mFill )
1616  {
1617  mFill->stopRender( context.renderContext() );
1618  }
1619 }
1620 
1622 {
1623  QgsStringMap map;
1624  map[QStringLiteral( "name" )] = encodeShape( mShape );
1625  map[QStringLiteral( "size" )] = QString::number( mSize );
1626  map[QStringLiteral( "size_unit" )] = QgsUnitTypes::encodeUnit( mSizeUnit );
1627  map[QStringLiteral( "size_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mSizeMapUnitScale );
1628  map[QStringLiteral( "angle" )] = QString::number( mAngle );
1629  map[QStringLiteral( "offset" )] = QgsSymbolLayerUtils::encodePoint( mOffset );
1630  map[QStringLiteral( "offset_unit" )] = QgsUnitTypes::encodeUnit( mOffsetUnit );
1631  map[QStringLiteral( "offset_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mOffsetMapUnitScale );
1632  map[QStringLiteral( "scale_method" )] = QgsSymbolLayerUtils::encodeScaleMethod( mScaleMethod );
1633  map[QStringLiteral( "horizontal_anchor_point" )] = QString::number( mHorizontalAnchorPoint );
1634  map[QStringLiteral( "vertical_anchor_point" )] = QString::number( mVerticalAnchorPoint );
1635 
1636  if ( mFill )
1637  {
1638  map[QStringLiteral( "color" )] = QgsSymbolLayerUtils::encodeColor( mFill->color() );
1639  }
1640  return map;
1641 }
1642 
1644 {
1646  copyPaintEffect( m );
1648  m->setSubSymbol( mFill->clone() );
1649  return m;
1650 }
1651 
1653 {
1654  return mFill.get();
1655 }
1656 
1658 {
1659  if ( symbol && symbol->type() == QgsSymbol::Fill )
1660  {
1661  mFill.reset( static_cast<QgsFillSymbol *>( symbol ) );
1662  return true;
1663  }
1664  else
1665  {
1666  delete symbol;
1667  return false;
1668  }
1669 }
1670 
1672 {
1673  if ( mFill )
1674  {
1675  return QgsSymbolLayerUtils::estimateMaxSymbolBleed( mFill.get(), context );
1676  }
1677  return 0;
1678 }
1679 
1681 {
1682  QSet<QString> attr = QgsSimpleMarkerSymbolLayerBase::usedAttributes( context );
1683  if ( mFill )
1684  attr.unite( mFill->usedAttributes( context ) );
1685  return attr;
1686 }
1687 
1689 {
1691  return true;
1692  if ( mFill && mFill->hasDataDefinedProperties() )
1693  return true;
1694  return false;
1695 }
1696 
1698 {
1699  mColor = c;
1700  if ( mFill )
1701  mFill->setColor( c );
1702 }
1703 
1705 {
1706  return mFill ? mFill->color() : mColor;
1707 }
1708 
1709 void QgsFilledMarkerSymbolLayer::draw( QgsSymbolRenderContext &context, QgsSimpleMarkerSymbolLayerBase::Shape shape, const QPolygonF &polygon, const QPainterPath &path )
1710 {
1711  //making changes here? Don't forget to also update ::bounds if the changes affect the bounding box
1712  //of the rendered point!
1713 
1714  QPainter *p = context.renderContext().painter();
1715  if ( !p )
1716  {
1717  return;
1718  }
1719 
1720  if ( shapeIsFilled( shape ) )
1721  {
1722  p->setBrush( Qt::red );
1723  }
1724  else
1725  {
1726  p->setBrush( Qt::NoBrush );
1727  }
1728  p->setPen( Qt::black );
1729 
1730  if ( !polygon.isEmpty() )
1731  {
1732  mFill->renderPolygon( polygon, /* rings */ nullptr, context.feature(), context.renderContext(), -1, context.selected() );
1733  }
1734  else
1735  {
1736  QPolygonF poly = path.toFillPolygon();
1737  mFill->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext(), -1, context.selected() );
1738  }
1739 
1740 
1741 }
1742 
1743 
1745 
1746 
1747 QgsSvgMarkerSymbolLayer::QgsSvgMarkerSymbolLayer( const QString &path, double size, double angle, QgsSymbol::ScaleMethod scaleMethod )
1748 {
1749  mSize = size;
1750  mAngle = angle;
1751  mOffset = QPointF( 0, 0 );
1753  mStrokeWidth = 0.2;
1755  mColor = QColor( 35, 35, 35 );
1756  mStrokeColor = QColor( 35, 35, 35 );
1757  setPath( path );
1758 }
1759 
1760 
1762 {
1763  QString name;
1764  double size = DEFAULT_SVGMARKER_SIZE;
1765  double angle = DEFAULT_SVGMARKER_ANGLE;
1767 
1768  if ( props.contains( QStringLiteral( "name" ) ) )
1769  name = props[QStringLiteral( "name" )];
1770  if ( props.contains( QStringLiteral( "size" ) ) )
1771  size = props[QStringLiteral( "size" )].toDouble();
1772  if ( props.contains( QStringLiteral( "angle" ) ) )
1773  angle = props[QStringLiteral( "angle" )].toDouble();
1774  if ( props.contains( QStringLiteral( "scale_method" ) ) )
1775  scaleMethod = QgsSymbolLayerUtils::decodeScaleMethod( props[QStringLiteral( "scale_method" )] );
1776 
1778 
1779  if ( props.contains( QStringLiteral( "size_unit" ) ) )
1780  m->setSizeUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "size_unit" )] ) );
1781  if ( props.contains( QStringLiteral( "size_map_unit_scale" ) ) )
1782  m->setSizeMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "size_map_unit_scale" )] ) );
1783  if ( props.contains( QStringLiteral( "fixedAspectRatio" ) ) )
1784  m->setFixedAspectRatio( props[QStringLiteral( "fixedAspectRatio" )].toDouble() );
1785  if ( props.contains( QStringLiteral( "offset" ) ) )
1786  m->setOffset( QgsSymbolLayerUtils::decodePoint( props[QStringLiteral( "offset" )] ) );
1787  if ( props.contains( QStringLiteral( "offset_unit" ) ) )
1788  m->setOffsetUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "offset_unit" )] ) );
1789  if ( props.contains( QStringLiteral( "offset_map_unit_scale" ) ) )
1790  m->setOffsetMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "offset_map_unit_scale" )] ) );
1791  if ( props.contains( QStringLiteral( "fill" ) ) )
1792  {
1793  //pre 2.5 projects used "fill"
1794  m->setFillColor( QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "fill" )] ) );
1795  }
1796  else if ( props.contains( QStringLiteral( "color" ) ) )
1797  {
1798  m->setFillColor( QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "color" )] ) );
1799  }
1800  if ( props.contains( QStringLiteral( "outline" ) ) )
1801  {
1802  //pre 2.5 projects used "outline"
1803  m->setStrokeColor( QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "outline" )] ) );
1804  }
1805  else if ( props.contains( QStringLiteral( "outline_color" ) ) )
1806  {
1807  m->setStrokeColor( QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "outline_color" )] ) );
1808  }
1809  else if ( props.contains( QStringLiteral( "line_color" ) ) )
1810  {
1811  m->setStrokeColor( QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "line_color" )] ) );
1812  }
1813 
1814  if ( props.contains( QStringLiteral( "outline-width" ) ) )
1815  {
1816  //pre 2.5 projects used "outline-width"
1817  m->setStrokeWidth( props[QStringLiteral( "outline-width" )].toDouble() );
1818  }
1819  else if ( props.contains( QStringLiteral( "outline_width" ) ) )
1820  {
1821  m->setStrokeWidth( props[QStringLiteral( "outline_width" )].toDouble() );
1822  }
1823  else if ( props.contains( QStringLiteral( "line_width" ) ) )
1824  {
1825  m->setStrokeWidth( props[QStringLiteral( "line_width" )].toDouble() );
1826  }
1827 
1828  if ( props.contains( QStringLiteral( "outline_width_unit" ) ) )
1829  {
1830  m->setStrokeWidthUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "outline_width_unit" )] ) );
1831  }
1832  else if ( props.contains( QStringLiteral( "line_width_unit" ) ) )
1833  {
1834  m->setStrokeWidthUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "line_width_unit" )] ) );
1835  }
1836  if ( props.contains( QStringLiteral( "outline_width_map_unit_scale" ) ) )
1837  m->setStrokeWidthMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "outline_width_map_unit_scale" )] ) );
1838 
1839  if ( props.contains( QStringLiteral( "horizontal_anchor_point" ) ) )
1840  {
1841  m->setHorizontalAnchorPoint( QgsMarkerSymbolLayer::HorizontalAnchorPoint( props[ QStringLiteral( "horizontal_anchor_point" )].toInt() ) );
1842  }
1843  if ( props.contains( QStringLiteral( "vertical_anchor_point" ) ) )
1844  {
1845  m->setVerticalAnchorPoint( QgsMarkerSymbolLayer::VerticalAnchorPoint( props[ QStringLiteral( "vertical_anchor_point" )].toInt() ) );
1846  }
1847 
1848  m->restoreOldDataDefinedProperties( props );
1849 
1851 
1852  return m;
1853 }
1854 
1855 void QgsSvgMarkerSymbolLayer::resolvePaths( QgsStringMap &properties, const QgsPathResolver &pathResolver, bool saving )
1856 {
1857  QgsStringMap::iterator it = properties.find( QStringLiteral( "name" ) );
1858  if ( it != properties.end() )
1859  {
1860  if ( saving )
1861  it.value() = QgsSymbolLayerUtils::svgSymbolPathToName( it.value(), pathResolver );
1862  else
1863  it.value() = QgsSymbolLayerUtils::svgSymbolNameToPath( it.value(), pathResolver );
1864  }
1865 }
1866 
1867 void QgsSvgMarkerSymbolLayer::setPath( const QString &path )
1868 {
1869  mDefaultAspectRatio = 0;
1870  mHasFillParam = false;
1871  mPath = path;
1872  QColor defaultFillColor, defaultStrokeColor;
1873  double strokeWidth, fillOpacity, strokeOpacity;
1874  bool hasFillOpacityParam = false, hasStrokeParam = false, hasStrokeWidthParam = false, hasStrokeOpacityParam = false;
1875  bool hasDefaultFillColor = false, hasDefaultFillOpacity = false, hasDefaultStrokeColor = false, hasDefaultStrokeWidth = false, hasDefaultStrokeOpacity = false;
1876  QgsApplication::svgCache()->containsParams( path, mHasFillParam, hasDefaultFillColor, defaultFillColor,
1877  hasFillOpacityParam, hasDefaultFillOpacity, fillOpacity,
1878  hasStrokeParam, hasDefaultStrokeColor, defaultStrokeColor,
1879  hasStrokeWidthParam, hasDefaultStrokeWidth, strokeWidth,
1880  hasStrokeOpacityParam, hasDefaultStrokeOpacity, strokeOpacity );
1881 
1882  double newFillOpacity = hasFillOpacityParam ? fillColor().alphaF() : 1.0;
1883  double newStrokeOpacity = hasStrokeOpacityParam ? strokeColor().alphaF() : 1.0;
1884 
1885  if ( hasDefaultFillColor )
1886  {
1887  defaultFillColor.setAlphaF( newFillOpacity );
1888  setFillColor( defaultFillColor );
1889  }
1890  if ( hasDefaultFillOpacity )
1891  {
1892  QColor c = fillColor();
1893  c.setAlphaF( fillOpacity );
1894  setFillColor( c );
1895  }
1896  if ( hasDefaultStrokeColor )
1897  {
1898  defaultStrokeColor.setAlphaF( newStrokeOpacity );
1899  setStrokeColor( defaultStrokeColor );
1900  }
1901  if ( hasDefaultStrokeWidth )
1902  {
1904  }
1905  if ( hasDefaultStrokeOpacity )
1906  {
1907  QColor c = strokeColor();
1908  c.setAlphaF( strokeOpacity );
1909  setStrokeColor( c );
1910  }
1911 
1913 }
1914 
1916 {
1917  if ( mDefaultAspectRatio == 0.0 )
1918  {
1919  //size
1920  double size = mSize;
1921  //assume 88 dpi as standard value
1922  double widthScaleFactor = 3.465;
1923  QSizeF svgViewbox = QgsApplication::svgCache()->svgViewboxSize( mPath, size, mColor, mStrokeColor, mStrokeWidth, widthScaleFactor );
1924  // set default aspect ratio
1925  mDefaultAspectRatio = svgViewbox.isValid() ? svgViewbox.height() / svgViewbox.width() : 0.0;
1926  }
1927  return mDefaultAspectRatio;
1928 }
1929 
1931 {
1932  bool aPreservedAspectRatio = preservedAspectRatio();
1933  if ( aPreservedAspectRatio && !par )
1934  {
1936  }
1937  else if ( !aPreservedAspectRatio && par )
1938  {
1939  mFixedAspectRatio = 0.0;
1940  }
1941  return preservedAspectRatio();
1942 }
1943 
1944 
1946 {
1947  return QStringLiteral( "SvgMarker" );
1948 }
1949 
1951 {
1952  QgsMarkerSymbolLayer::startRender( context ); // get anchor point expressions
1953  Q_UNUSED( context )
1954 }
1955 
1957 {
1958  Q_UNUSED( context )
1959 }
1960 
1962 {
1963  QPainter *p = context.renderContext().painter();
1964  if ( !p )
1965  return;
1966 
1967  bool hasDataDefinedSize = false;
1968  double scaledWidth = calculateSize( context, hasDataDefinedSize );
1969  double width = context.renderContext().convertToPainterUnits( scaledWidth, mSizeUnit, mSizeMapUnitScale );
1970 
1971  //don't render symbols with a width below one or above 10,000 pixels
1972  if ( static_cast< int >( width ) < 1 || 10000.0 < width )
1973  {
1974  return;
1975  }
1976 
1977  QgsScopedQPainterState painterState( p );
1978 
1979  bool hasDataDefinedAspectRatio = false;
1980  double aspectRatio = calculateAspectRatio( context, scaledWidth, hasDataDefinedAspectRatio );
1981  double scaledHeight = scaledWidth * ( !qgsDoubleNear( aspectRatio, 0.0 ) ? aspectRatio : mDefaultAspectRatio );
1982 
1983  double strokeWidth = mStrokeWidth;
1985  {
1988  }
1990 
1991  QColor fillColor = mColor;
1992  if ( context.selected() && mHasFillParam )
1993  {
1994  fillColor = context.renderContext().selectionColor();
1995  }
1997  {
2000  }
2001 
2002  QColor strokeColor = mStrokeColor;
2004  {
2007  }
2008 
2009  QString path = mPath;
2011  {
2012  context.setOriginalValueVariable( mPath );
2014  context.renderContext().pathResolver() );
2016  {
2017  // adjust height of data defined path
2018  QSizeF svgViewbox = QgsApplication::svgCache()->svgViewboxSize( path, scaledWidth, fillColor, strokeColor, strokeWidth,
2019  context.renderContext().scaleFactor(), aspectRatio,
2021  scaledHeight = svgViewbox.isValid() ? scaledWidth * svgViewbox.height() / svgViewbox.width() : scaledWidth;
2022  }
2023  }
2024 
2025  QPointF outputOffset;
2026  double angle = 0.0;
2027  calculateOffsetAndRotation( context, scaledWidth, scaledHeight, outputOffset, angle );
2028 
2029  p->translate( point + outputOffset );
2030 
2031  bool rotated = !qgsDoubleNear( angle, 0 );
2032  if ( rotated )
2033  p->rotate( angle );
2034 
2035  bool fitsInCache = true;
2036  bool usePict = true;
2038  if ( ( !context.renderContext().forceVectorOutput() && !rotated ) || ( context.selected() && rasterizeSelected ) )
2039  {
2041  context.renderContext().scaleFactor(), fitsInCache, aspectRatio,
2043  if ( fitsInCache && img.width() > 1 )
2044  {
2045  usePict = false;
2046 
2047  if ( context.selected() )
2049 
2050  //consider transparency
2051  if ( !qgsDoubleNear( context.opacity(), 1.0 ) )
2052  {
2053  QImage transparentImage = img.copy();
2054  QgsSymbolLayerUtils::multiplyImageOpacity( &transparentImage, context.opacity() );
2055  p->drawImage( -transparentImage.width() / 2.0, -transparentImage.height() / 2.0, transparentImage );
2056  }
2057  else
2058  {
2059  p->drawImage( -img.width() / 2.0, -img.height() / 2.0, img );
2060  }
2061  }
2062  }
2063 
2064  if ( usePict || !fitsInCache )
2065  {
2066  p->setOpacity( context.opacity() );
2068  context.renderContext().scaleFactor(), context.renderContext().forceVectorOutput(), aspectRatio,
2070  if ( pct.width() > 1 )
2071  {
2072  QgsScopedQPainterState painterPictureState( p );
2073  _fixQPictureDPI( p );
2074  p->drawPicture( 0, 0, pct );
2075  }
2076  }
2077 
2078  // workaround issue with nested QPictures forgetting antialiasing flag - see https://github.com/qgis/QGIS/issues/22909
2080 }
2081 
2082 double QgsSvgMarkerSymbolLayer::calculateSize( QgsSymbolRenderContext &context, bool &hasDataDefinedSize ) const
2083 {
2084  double scaledSize = mSize;
2086 
2087  bool ok = true;
2088  if ( hasDataDefinedSize )
2089  {
2090  context.setOriginalValueVariable( mSize );
2092  }
2093  else
2094  {
2096  if ( hasDataDefinedSize )
2097  {
2098  context.setOriginalValueVariable( mSize );
2100  }
2101  }
2102 
2103  if ( hasDataDefinedSize && ok )
2104  {
2105  switch ( mScaleMethod )
2106  {
2107  case QgsSymbol::ScaleArea:
2108  scaledSize = std::sqrt( scaledSize );
2109  break;
2111  break;
2112  }
2113  }
2114 
2115  return scaledSize;
2116 }
2117 
2118 double QgsSvgMarkerSymbolLayer::calculateAspectRatio( QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedAspectRatio ) const
2119 {
2121  if ( !hasDataDefinedAspectRatio )
2122  return mFixedAspectRatio;
2123 
2125  return 0.0;
2126 
2127  double scaledAspectRatio = mDefaultAspectRatio;
2128  if ( mFixedAspectRatio > 0.0 )
2129  scaledAspectRatio = mFixedAspectRatio;
2130 
2131  double defaultHeight = mSize * scaledAspectRatio;
2132  scaledAspectRatio = defaultHeight / scaledSize;
2133 
2134  bool ok = true;
2135  double scaledHeight = scaledSize * scaledAspectRatio;
2137  {
2138  context.setOriginalValueVariable( defaultHeight );
2139  scaledHeight = mDataDefinedProperties.valueAsDouble( QgsSymbolLayer::PropertyHeight, context.renderContext().expressionContext(), defaultHeight, &ok );
2140  }
2141 
2142  if ( hasDataDefinedAspectRatio && ok )
2143  {
2144  switch ( mScaleMethod )
2145  {
2146  case QgsSymbol::ScaleArea:
2147  scaledHeight = sqrt( scaledHeight );
2148  break;
2150  break;
2151  }
2152  }
2153 
2154  scaledAspectRatio = scaledHeight / scaledSize;
2155 
2156  return scaledAspectRatio;
2157 }
2158 
2159 void QgsSvgMarkerSymbolLayer::calculateOffsetAndRotation( QgsSymbolRenderContext &context, double scaledWidth, double scaledHeight, QPointF &offset, double &angle ) const
2160 {
2161  //offset
2162  double offsetX = 0;
2163  double offsetY = 0;
2164  markerOffset( context, scaledWidth, scaledHeight, offsetX, offsetY );
2165  offset = QPointF( offsetX, offsetY );
2166 
2167  angle = mAngle + mLineAngle;
2169  {
2170  context.setOriginalValueVariable( mAngle );
2172  }
2173 
2175  if ( hasDataDefinedRotation )
2176  {
2177  // For non-point markers, "dataDefinedRotation" means following the
2178  // shape (shape-data defined). For them, "field-data defined" does
2179  // not work at all. TODO: if "field-data defined" ever gets implemented
2180  // we'll need a way to distinguish here between the two, possibly
2181  // using another flag in renderHints()
2182  const QgsFeature *f = context.feature();
2183  if ( f )
2184  {
2185  if ( f->hasGeometry() && f->geometry().type() == QgsWkbTypes::PointGeometry )
2186  {
2187  const QgsMapToPixel &m2p = context.renderContext().mapToPixel();
2188  angle += m2p.mapRotation();
2189  }
2190  }
2191  }
2192 
2193  if ( angle )
2195 }
2196 
2197 
2199 {
2200  QgsStringMap map;
2201  map[QStringLiteral( "name" )] = mPath;
2202  map[QStringLiteral( "size" )] = QString::number( mSize );
2203  map[QStringLiteral( "size_unit" )] = QgsUnitTypes::encodeUnit( mSizeUnit );
2204  map[QStringLiteral( "size_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mSizeMapUnitScale );
2205  map[QStringLiteral( "fixedAspectRatio" )] = QString::number( mFixedAspectRatio );
2206  map[QStringLiteral( "angle" )] = QString::number( mAngle );
2207  map[QStringLiteral( "offset" )] = QgsSymbolLayerUtils::encodePoint( mOffset );
2208  map[QStringLiteral( "offset_unit" )] = QgsUnitTypes::encodeUnit( mOffsetUnit );
2209  map[QStringLiteral( "offset_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mOffsetMapUnitScale );
2210  map[QStringLiteral( "scale_method" )] = QgsSymbolLayerUtils::encodeScaleMethod( mScaleMethod );
2211  map[QStringLiteral( "color" )] = QgsSymbolLayerUtils::encodeColor( mColor );
2212  map[QStringLiteral( "outline_color" )] = QgsSymbolLayerUtils::encodeColor( mStrokeColor );
2213  map[QStringLiteral( "outline_width" )] = QString::number( mStrokeWidth );
2214  map[QStringLiteral( "outline_width_unit" )] = QgsUnitTypes::encodeUnit( mStrokeWidthUnit );
2215  map[QStringLiteral( "outline_width_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mStrokeWidthMapUnitScale );
2216  map[QStringLiteral( "horizontal_anchor_point" )] = QString::number( mHorizontalAnchorPoint );
2217  map[QStringLiteral( "vertical_anchor_point" )] = QString::number( mVerticalAnchorPoint );
2218  return map;
2219 }
2220 
2222 {
2225  m->setColor( mColor );
2230  m->setOffset( mOffset );
2231  m->setOffsetUnit( mOffsetUnit );
2233  m->setSizeUnit( mSizeUnit );
2238  copyPaintEffect( m );
2239  return m;
2240 }
2241 
2243 {
2245  mStrokeWidthUnit = unit;
2246 }
2247 
2249 {
2251  if ( unit != mStrokeWidthUnit )
2252  {
2254  }
2255  return unit;
2256 }
2257 
2259 {
2261  mStrokeWidthMapUnitScale = scale;
2262 }
2263 
2265 {
2267  {
2268  return mStrokeWidthMapUnitScale;
2269  }
2270  return QgsMapUnitScale();
2271 }
2272 
2273 void QgsSvgMarkerSymbolLayer::writeSldMarker( QDomDocument &doc, QDomElement &element, const QgsStringMap &props ) const
2274 {
2275  // <Graphic>
2276  QDomElement graphicElem = doc.createElement( QStringLiteral( "se:Graphic" ) );
2277  element.appendChild( graphicElem );
2278 
2279  // encode a parametric SVG reference
2283 
2284  // <Rotation>
2285  QString angleFunc;
2286  bool ok;
2287  double angle = props.value( QStringLiteral( "angle" ), QStringLiteral( "0" ) ).toDouble( &ok );
2288  if ( !ok )
2289  {
2290  angleFunc = QStringLiteral( "%1 + %2" ).arg( props.value( QStringLiteral( "angle" ), QStringLiteral( "0" ) ) ).arg( mAngle );
2291  }
2292  else if ( !qgsDoubleNear( angle + mAngle, 0.0 ) )
2293  {
2294  angleFunc = QString::number( angle + mAngle );
2295  }
2296 
2297  QgsSymbolLayerUtils::createRotationElement( doc, graphicElem, angleFunc );
2298 
2299  // <Displacement>
2302 }
2303 
2305 {
2306  QgsDebugMsgLevel( QStringLiteral( "Entered." ), 4 );
2307 
2308  QDomElement graphicElem = element.firstChildElement( QStringLiteral( "Graphic" ) );
2309  if ( graphicElem.isNull() )
2310  return nullptr;
2311 
2312  QString path, mimeType;
2313  QColor fillColor;
2314  double size;
2315 
2316  if ( !QgsSymbolLayerUtils::externalGraphicFromSld( graphicElem, path, mimeType, fillColor, size ) )
2317  return nullptr;
2318 
2319  QString uom = element.attribute( QStringLiteral( "uom" ) );
2321 
2322  if ( mimeType != QLatin1String( "image/svg+xml" ) )
2323  return nullptr;
2324 
2325  double angle = 0.0;
2326  QString angleFunc;
2327  if ( QgsSymbolLayerUtils::rotationFromSldElement( graphicElem, angleFunc ) )
2328  {
2329  bool ok;
2330  double d = angleFunc.toDouble( &ok );
2331  if ( ok )
2332  angle = d;
2333  }
2334 
2335  QPointF offset;
2337 
2339  m->setOutputUnit( QgsUnitTypes::RenderUnit::RenderPixels );
2340  m->setFillColor( fillColor );
2341  //m->setStrokeColor( strokeColor );
2342  //m->setStrokeWidth( strokeWidth );
2343  m->setAngle( angle );
2344  m->setOffset( offset );
2345  return m;
2346 }
2347 
2348 bool QgsSvgMarkerSymbolLayer::writeDxf( QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, QgsSymbolRenderContext &context, QPointF shift ) const
2349 {
2350  //size
2351  double size = mSize;
2352 
2353  bool hasDataDefinedSize = mDataDefinedProperties.isActive( QgsSymbolLayer::PropertySize );
2354 
2355  bool ok = true;
2356  if ( hasDataDefinedSize )
2357  {
2358  context.setOriginalValueVariable( mSize );
2360  }
2361 
2362  if ( hasDataDefinedSize && ok )
2363  {
2364  switch ( mScaleMethod )
2365  {
2366  case QgsSymbol::ScaleArea:
2367  size = std::sqrt( size );
2368  break;
2370  break;
2371  }
2372  }
2373 
2375  {
2376  size *= mmMapUnitScaleFactor;
2377  }
2378 
2379  //offset, angle
2380  QPointF offset = mOffset;
2381 
2383  {
2385  const QVariant val = mDataDefinedProperties.value( QgsSymbolLayer::PropertyOffset, context.renderContext().expressionContext(), QString() );
2386  const QPointF res = QgsSymbolLayerUtils::toPoint( val, &ok );
2387  if ( ok )
2388  offset = res;
2389  }
2390  double offsetX = offset.x();
2391  double offsetY = offset.y();
2392 
2393  QPointF outputOffset( offsetX, offsetY );
2394 
2395  double angle = mAngle + mLineAngle;
2397  {
2398  context.setOriginalValueVariable( mAngle );
2400  }
2401 
2402  if ( angle )
2403  outputOffset = _rotatedOffset( outputOffset, angle );
2404 
2405  outputOffset *= e.mapUnitScaleFactor( e.symbologyScale(), mOffsetUnit, e.mapUnits(), context.renderContext().mapToPixel().mapUnitsPerPixel() );
2406 
2407  QString path = mPath;
2409  {
2410  context.setOriginalValueVariable( mPath );
2412  context.renderContext().pathResolver() );
2413  }
2414 
2415  double strokeWidth = mStrokeWidth;
2417  {
2420  }
2422 
2423  QColor fillColor = mColor;
2425  {
2428  }
2429 
2430  QColor strokeColor = mStrokeColor;
2432  {
2435  }
2436 
2437  const QByteArray &svgContent = QgsApplication::svgCache()->svgContent( path, size, fillColor, strokeColor, strokeWidth,
2440 
2441  QSvgRenderer r( svgContent );
2442  if ( !r.isValid() )
2443  return false;
2444 
2445  QgsDxfPaintDevice pd( &e );
2446  pd.setDrawingSize( QSizeF( r.defaultSize() ) );
2447 
2448  QSizeF outSize( r.defaultSize() );
2449  outSize.scale( size, size, Qt::KeepAspectRatio );
2450 
2451  QPainter p;
2452  p.begin( &pd );
2453  if ( !qgsDoubleNear( angle, 0.0 ) )
2454  {
2455  p.translate( r.defaultSize().width() / 2.0, r.defaultSize().height() / 2.0 );
2456  p.rotate( angle );
2457  p.translate( -r.defaultSize().width() / 2.0, -r.defaultSize().height() / 2.0 );
2458  }
2459  pd.setShift( shift + QPointF( outputOffset.x(), -outputOffset.y() ) );
2460  pd.setOutputSize( QRectF( -outSize.width() / 2.0, -outSize.height() / 2.0, outSize.width(), outSize.height() ) );
2461  pd.setLayer( layerName );
2462  r.render( &p );
2463  p.end();
2464  return true;
2465 }
2466 
2468 {
2469  bool hasDataDefinedSize = false;
2470  double scaledWidth = calculateSize( context, hasDataDefinedSize );
2471 
2472  bool hasDataDefinedAspectRatio = false;
2473  double aspectRatio = calculateAspectRatio( context, scaledWidth, hasDataDefinedAspectRatio );
2474  double scaledHeight = scaledWidth * ( !qgsDoubleNear( aspectRatio, 0.0 ) ? aspectRatio : mDefaultAspectRatio );
2475 
2476  scaledWidth = context.renderContext().convertToPainterUnits( scaledWidth, mSizeUnit, mSizeMapUnitScale );
2477  scaledHeight = context.renderContext().convertToPainterUnits( scaledHeight, mSizeUnit, mSizeMapUnitScale );
2478 
2479  //don't render symbols with size below one or above 10,000 pixels
2480  if ( static_cast< int >( scaledWidth ) < 1 || 10000.0 < scaledWidth )
2481  {
2482  return QRectF();
2483  }
2484 
2485  QPointF outputOffset;
2486  double angle = 0.0;
2487  calculateOffsetAndRotation( context, scaledWidth, scaledHeight, outputOffset, angle );
2488 
2489  double strokeWidth = mStrokeWidth;
2491  {
2494  }
2496 
2497  QString path = mPath;
2499  {
2500  context.setOriginalValueVariable( mPath );
2502  context.renderContext().pathResolver() );
2504  {
2505  // need to get colors to take advantage of cached SVGs
2506  QColor fillColor = mColor;
2508  {
2511  }
2512 
2513  QColor strokeColor = mStrokeColor;
2515  {
2518  }
2519 
2520  // adjust height of data defined path
2521  QSizeF svgViewbox = QgsApplication::svgCache()->svgViewboxSize( path, scaledWidth, fillColor, strokeColor, strokeWidth,
2522  context.renderContext().scaleFactor(), aspectRatio,
2524  scaledHeight = svgViewbox.isValid() ? scaledWidth * svgViewbox.height() / svgViewbox.width() : scaledWidth;
2525  }
2526  }
2527 
2528  QMatrix transform;
2529  // move to the desired position
2530  transform.translate( point.x() + outputOffset.x(), point.y() + outputOffset.y() );
2531 
2532  if ( !qgsDoubleNear( angle, 0.0 ) )
2533  transform.rotate( angle );
2534 
2535  //antialiasing
2536  strokeWidth += 1.0 / 2.0;
2537 
2538  QRectF symbolBounds = transform.mapRect( QRectF( -scaledWidth / 2.0,
2539  -scaledHeight / 2.0,
2540  scaledWidth,
2541  scaledHeight ) );
2542 
2543  //extend bounds by pen width / 2.0
2544  symbolBounds.adjust( -strokeWidth / 2.0, -strokeWidth / 2.0,
2545  strokeWidth / 2.0, strokeWidth / 2.0 );
2546 
2547  return symbolBounds;
2548 }
2549 
2551 
2552 QgsRasterMarkerSymbolLayer::QgsRasterMarkerSymbolLayer( const QString &path, double size, double angle, QgsSymbol::ScaleMethod scaleMethod )
2553  : mPath( path )
2554 {
2555  mSize = size;
2556  mAngle = angle;
2557  mOffset = QPointF( 0, 0 );
2560 }
2561 
2562 
2564 {
2565  QString path;
2569 
2570  if ( props.contains( QStringLiteral( "imageFile" ) ) )
2571  path = props[QStringLiteral( "imageFile" )];
2572  if ( props.contains( QStringLiteral( "size" ) ) )
2573  size = props[QStringLiteral( "size" )].toDouble();
2574  if ( props.contains( QStringLiteral( "angle" ) ) )
2575  angle = props[QStringLiteral( "angle" )].toDouble();
2576  if ( props.contains( QStringLiteral( "scale_method" ) ) )
2577  scaleMethod = QgsSymbolLayerUtils::decodeScaleMethod( props[QStringLiteral( "scale_method" )] );
2578 
2580 
2581  if ( props.contains( QStringLiteral( "alpha" ) ) )
2582  {
2583  m->setOpacity( props[QStringLiteral( "alpha" )].toDouble() );
2584  }
2585 
2586  if ( props.contains( QStringLiteral( "size_unit" ) ) )
2587  m->setSizeUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "size_unit" )] ) );
2588  if ( props.contains( QStringLiteral( "size_map_unit_scale" ) ) )
2589  m->setSizeMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "size_map_unit_scale" )] ) );
2590  if ( props.contains( QStringLiteral( "fixedAspectRatio" ) ) )
2591  m->setFixedAspectRatio( props[QStringLiteral( "fixedAspectRatio" )].toDouble() );
2592 
2593  if ( props.contains( QStringLiteral( "offset" ) ) )
2594  m->setOffset( QgsSymbolLayerUtils::decodePoint( props[QStringLiteral( "offset" )] ) );
2595  if ( props.contains( QStringLiteral( "offset_unit" ) ) )
2596  m->setOffsetUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "offset_unit" )] ) );
2597  if ( props.contains( QStringLiteral( "offset_map_unit_scale" ) ) )
2598  m->setOffsetMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "offset_map_unit_scale" )] ) );
2599 
2600  if ( props.contains( QStringLiteral( "horizontal_anchor_point" ) ) )
2601  {
2602  m->setHorizontalAnchorPoint( QgsMarkerSymbolLayer::HorizontalAnchorPoint( props[ QStringLiteral( "horizontal_anchor_point" )].toInt() ) );
2603  }
2604  if ( props.contains( QStringLiteral( "vertical_anchor_point" ) ) )
2605  {
2606  m->setVerticalAnchorPoint( QgsMarkerSymbolLayer::VerticalAnchorPoint( props[ QStringLiteral( "vertical_anchor_point" )].toInt() ) );
2607  }
2608 
2609  m->restoreOldDataDefinedProperties( props );
2611 
2612  return m;
2613 }
2614 
2615 void QgsRasterMarkerSymbolLayer::resolvePaths( QgsStringMap &properties, const QgsPathResolver &pathResolver, bool saving )
2616 {
2617  QgsStringMap::iterator it = properties.find( QStringLiteral( "name" ) );
2618  if ( it != properties.end() )
2619  {
2620  if ( saving )
2621  it.value() = QgsSymbolLayerUtils::svgSymbolPathToName( it.value(), pathResolver );
2622  else
2623  it.value() = QgsSymbolLayerUtils::svgSymbolNameToPath( it.value(), pathResolver );
2624  }
2625 }
2626 
2627 void QgsRasterMarkerSymbolLayer::setPath( const QString &path )
2628 {
2629  mPath = path;
2631 }
2632 
2634 {
2635  bool aPreservedAspectRatio = preservedAspectRatio();
2636  if ( aPreservedAspectRatio && !par )
2637  {
2639  }
2640  else if ( !aPreservedAspectRatio && par )
2641  {
2642  mFixedAspectRatio = 0.0;
2643  }
2644  return preservedAspectRatio();
2645 }
2646 
2648 {
2649  if ( mDefaultAspectRatio == 0.0 )
2650  {
2652  mDefaultAspectRatio = ( !size.isNull() && size.isValid() && size.width() > 0 ) ? static_cast< double >( size.height() ) / static_cast< double >( size.width() ) : 0.0;
2653  }
2654  return mDefaultAspectRatio;
2655 }
2656 
2658 {
2659  return QStringLiteral( "RasterMarker" );
2660 }
2661 
2663 {
2664  QPainter *p = context.renderContext().painter();
2665  if ( !p )
2666  return;
2667 
2668  QString path = mPath;
2670  {
2671  context.setOriginalValueVariable( mPath );
2673  }
2674 
2675  if ( path.isEmpty() )
2676  return;
2677 
2678  double width = 0.0;
2679  double height = 0.0;
2680 
2681  bool hasDataDefinedSize = false;
2682  double scaledSize = calculateSize( context, hasDataDefinedSize );
2683 
2684  bool hasDataDefinedAspectRatio = false;
2685  double aspectRatio = calculateAspectRatio( context, scaledSize, hasDataDefinedAspectRatio );
2686 
2687  QPointF outputOffset;
2688  double angle = 0.0;
2689 
2690  // RenderPercentage Unit Type takes original image size
2692  {
2694  if ( size.isEmpty() )
2695  return;
2696 
2697  width = ( scaledSize * static_cast< double >( size.width() ) ) / 100.0;
2698  height = ( scaledSize * static_cast< double >( size.height() ) ) / 100.0;
2699 
2700  // don't render symbols with size below one or above 10,000 pixels
2701  if ( static_cast< int >( width ) < 1 || 10000.0 < width || static_cast< int >( height ) < 1 || 10000.0 < height )
2702  return;
2703 
2704  calculateOffsetAndRotation( context, width, height, outputOffset, angle );
2705  }
2706  else
2707  {
2708  width = context.renderContext().convertToPainterUnits( scaledSize, mSizeUnit, mSizeMapUnitScale );
2709  height = width * ( preservedAspectRatio() ? defaultAspectRatio() : aspectRatio );
2710 
2711  if ( preservedAspectRatio() && path != mPath )
2712  {
2714  if ( !size.isNull() && size.isValid() && size.width() > 0 )
2715  {
2716  height = width * ( static_cast< double >( size.height() ) / static_cast< double >( size.width() ) );
2717  }
2718  }
2719 
2720  // don't render symbols with size below one or above 10,000 pixels
2721  if ( static_cast< int >( width ) < 1 || 10000.0 < width )
2722  return;
2723 
2724  calculateOffsetAndRotation( context, scaledSize, scaledSize * ( height / width ), outputOffset, angle );
2725  }
2726 
2727  QgsScopedQPainterState painterState( p );
2728  p->translate( point + outputOffset );
2729 
2730  bool rotated = !qgsDoubleNear( angle, 0 );
2731  if ( rotated )
2732  p->rotate( angle );
2733 
2734  double opacity = mOpacity;
2736  {
2739  }
2740  opacity *= context.opacity();
2741 
2742  bool cached;
2743  QImage img = QgsApplication::imageCache()->pathAsImage( path, QSize( width, preservedAspectRatio() ? 0 : width * aspectRatio ), preservedAspectRatio(), opacity, cached, ( context.renderContext().flags() & QgsRenderContext::RenderBlocking ) );
2744  if ( !img.isNull() )
2745  {
2746  if ( context.selected() )
2748 
2749  p->drawImage( -img.width() / 2.0, -img.height() / 2.0, img );
2750  }
2751 }
2752 
2753 double QgsRasterMarkerSymbolLayer::calculateSize( QgsSymbolRenderContext &context, bool &hasDataDefinedSize ) const
2754 {
2755  double scaledSize = mSize;
2757 
2758  bool ok = true;
2759  if ( hasDataDefinedSize )
2760  {
2761  context.setOriginalValueVariable( mSize );
2763  }
2764  else
2765  {
2767  if ( hasDataDefinedSize )
2768  {
2769  context.setOriginalValueVariable( mSize );
2771  }
2772  }
2773 
2774  if ( hasDataDefinedSize && ok )
2775  {
2776  switch ( mScaleMethod )
2777  {
2778  case QgsSymbol::ScaleArea:
2779  scaledSize = std::sqrt( scaledSize );
2780  break;
2782  break;
2783  }
2784  }
2785 
2786  return scaledSize;
2787 }
2788 
2789 double QgsRasterMarkerSymbolLayer::calculateAspectRatio( QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedAspectRatio ) const
2790 {
2792  if ( !hasDataDefinedAspectRatio )
2793  return mFixedAspectRatio;
2794 
2796  return 0.0;
2797 
2798  double scaledAspectRatio = mDefaultAspectRatio;
2799  if ( mFixedAspectRatio > 0.0 )
2800  scaledAspectRatio = mFixedAspectRatio;
2801 
2802  double defaultHeight = mSize * scaledAspectRatio;
2803  scaledAspectRatio = defaultHeight / scaledSize;
2804 
2805  bool ok = true;
2806  double scaledHeight = scaledSize * scaledAspectRatio;
2808  {
2809  context.setOriginalValueVariable( defaultHeight );
2810  scaledHeight = mDataDefinedProperties.valueAsDouble( QgsSymbolLayer::PropertyHeight, context.renderContext().expressionContext(), defaultHeight, &ok );
2811  }
2812 
2813  if ( hasDataDefinedAspectRatio && ok )
2814  {
2815  switch ( mScaleMethod )
2816  {
2817  case QgsSymbol::ScaleArea:
2818  scaledHeight = sqrt( scaledHeight );
2819  break;
2821  break;
2822  }
2823  }
2824 
2825  scaledAspectRatio = scaledHeight / scaledSize;
2826 
2827  return scaledAspectRatio;
2828 }
2829 
2830 void QgsRasterMarkerSymbolLayer::calculateOffsetAndRotation( QgsSymbolRenderContext &context, double scaledWidth, double scaledHeight, QPointF &offset, double &angle ) const
2831 {
2832  //offset
2833  double offsetX = 0;
2834  double offsetY = 0;
2835  markerOffset( context, scaledWidth, scaledHeight, offsetX, offsetY );
2836  offset = QPointF( offsetX, offsetY );
2837 
2838  angle = mAngle + mLineAngle;
2840  {
2841  context.setOriginalValueVariable( mAngle );
2843  }
2844 
2846  if ( hasDataDefinedRotation )
2847  {
2848  const QgsFeature *f = context.feature();
2849  if ( f )
2850  {
2851  if ( f->hasGeometry() && f->geometry().type() == QgsWkbTypes::PointGeometry )
2852  {
2853  const QgsMapToPixel &m2p = context.renderContext().mapToPixel();
2854  angle += m2p.mapRotation();
2855  }
2856  }
2857  }
2858 
2859  if ( angle )
2861 }
2862 
2863 
2865 {
2866  QgsStringMap map;
2867  map[QStringLiteral( "imageFile" )] = mPath;
2868  map[QStringLiteral( "size" )] = QString::number( mSize );
2869  map[QStringLiteral( "size_unit" )] = QgsUnitTypes::encodeUnit( mSizeUnit );
2870  map[QStringLiteral( "size_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mSizeMapUnitScale );
2871  map[QStringLiteral( "fixedAspectRatio" )] = QString::number( mFixedAspectRatio );
2872  map[QStringLiteral( "angle" )] = QString::number( mAngle );
2873  map[QStringLiteral( "alpha" )] = QString::number( mOpacity );
2874  map[QStringLiteral( "offset" )] = QgsSymbolLayerUtils::encodePoint( mOffset );
2875  map[QStringLiteral( "offset_unit" )] = QgsUnitTypes::encodeUnit( mOffsetUnit );
2876  map[QStringLiteral( "offset_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mOffsetMapUnitScale );
2877  map[QStringLiteral( "scale_method" )] = QgsSymbolLayerUtils::encodeScaleMethod( mScaleMethod );
2878  map[QStringLiteral( "horizontal_anchor_point" )] = QString::number( mHorizontalAnchorPoint );
2879  map[QStringLiteral( "vertical_anchor_point" )] = QString::number( mVerticalAnchorPoint );
2880  return map;
2881 }
2882 
2884 {
2887  m->setOpacity( mOpacity );
2888  m->setOffset( mOffset );
2889  m->setOffsetUnit( mOffsetUnit );
2891  m->setSizeUnit( mSizeUnit );
2896  copyPaintEffect( m );
2897  return m;
2898 }
2899 
2901 {
2903 }
2904 
2906 {
2908 }
2909 
2911 {
2912  bool hasDataDefinedSize = false;
2913  double scaledSize = calculateSize( context, hasDataDefinedSize );
2914  double width = context.renderContext().convertToPainterUnits( scaledSize, mSizeUnit, mSizeMapUnitScale );
2915  bool hasDataDefinedAspectRatio = false;
2916  double aspectRatio = calculateAspectRatio( context, scaledSize, hasDataDefinedAspectRatio );
2917  double height = width * ( preservedAspectRatio() ? defaultAspectRatio() : aspectRatio );
2918 
2919  //don't render symbols with size below one or above 10,000 pixels
2920  if ( static_cast< int >( scaledSize ) < 1 || 10000.0 < scaledSize )
2921  {
2922  return QRectF();
2923  }
2924 
2925  QPointF outputOffset;
2926  double angle = 0.0;
2927  calculateOffsetAndRotation( context, scaledSize, scaledSize * ( height / width ), outputOffset, angle );
2928 
2929  QMatrix transform;
2930 
2931  // move to the desired position
2932  transform.translate( point.x() + outputOffset.x(), point.y() + outputOffset.y() );
2933 
2934  if ( !qgsDoubleNear( angle, 0.0 ) )
2935  transform.rotate( angle );
2936 
2937  QRectF symbolBounds = transform.mapRect( QRectF( -width / 2.0,
2938  -height / 2.0,
2939  width,
2940  height ) );
2941 
2942  return symbolBounds;
2943 }
2944 
2946 
2947 QgsFontMarkerSymbolLayer::QgsFontMarkerSymbolLayer( const QString &fontFamily, QString chr, double pointSize, const QColor &color, double angle )
2948 {
2949  mFontFamily = fontFamily;
2950  mString = chr;
2951  mColor = color;
2952  mAngle = angle;
2953  mSize = pointSize;
2954  mOrigSize = pointSize;
2956  mOffset = QPointF( 0, 0 );
2958  mStrokeColor = DEFAULT_FONTMARKER_BORDERCOLOR;
2959  mStrokeWidth = 0.0;
2960  mStrokeWidthUnit = QgsUnitTypes::RenderMillimeters;
2961  mPenJoinStyle = DEFAULT_FONTMARKER_JOINSTYLE;
2962 }
2963 
2965 {
2968  QString string = DEFAULT_FONTMARKER_CHR;
2969  double pointSize = DEFAULT_FONTMARKER_SIZE;
2972 
2973  if ( props.contains( QStringLiteral( "font" ) ) )
2974  fontFamily = props[QStringLiteral( "font" )];
2975  if ( props.contains( QStringLiteral( "chr" ) ) && props[QStringLiteral( "chr" )].length() > 0 )
2976  string = props[QStringLiteral( "chr" )];
2977  if ( props.contains( QStringLiteral( "size" ) ) )
2978  pointSize = props[QStringLiteral( "size" )].toDouble();
2979  if ( props.contains( QStringLiteral( "color" ) ) )
2980  color = QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "color" )] );
2981  if ( props.contains( QStringLiteral( "angle" ) ) )
2982  angle = props[QStringLiteral( "angle" )].toDouble();
2983 
2984  QgsFontMarkerSymbolLayer *m = new QgsFontMarkerSymbolLayer( fontFamily, string, pointSize, color, angle );
2985 
2986  if ( props.contains( QStringLiteral( "font_style" ) ) )
2987  m->setFontStyle( props[QStringLiteral( "font_style" )] );
2988  if ( props.contains( QStringLiteral( "outline_color" ) ) )
2989  m->setStrokeColor( QgsSymbolLayerUtils::decodeColor( props[QStringLiteral( "outline_color" )] ) );
2990  if ( props.contains( QStringLiteral( "outline_width" ) ) )
2991  m->setStrokeWidth( props[QStringLiteral( "outline_width" )].toDouble() );
2992  if ( props.contains( QStringLiteral( "offset" ) ) )
2993  m->setOffset( QgsSymbolLayerUtils::decodePoint( props[QStringLiteral( "offset" )] ) );
2994  if ( props.contains( QStringLiteral( "offset_unit" ) ) )
2995  m->setOffsetUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "offset_unit" )] ) );
2996  if ( props.contains( QStringLiteral( "offset_map_unit_scale" ) ) )
2997  m->setOffsetMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "offset_map_unit_scale" )] ) );
2998  if ( props.contains( QStringLiteral( "size_unit" ) ) )
2999  m->setSizeUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "size_unit" )] ) );
3000  if ( props.contains( QStringLiteral( "size_map_unit_scale" ) ) )
3001  m->setSizeMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "size_map_unit_scale" )] ) );
3002  if ( props.contains( QStringLiteral( "outline_width_unit" ) ) )
3003  m->setStrokeWidthUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "outline_width_unit" )] ) );
3004  if ( props.contains( QStringLiteral( "outline_width_map_unit_scale" ) ) )
3005  m->setStrokeWidthMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( props[QStringLiteral( "outline_width_map_unit_scale" )] ) );
3006  if ( props.contains( QStringLiteral( "joinstyle" ) ) )
3007  m->setPenJoinStyle( QgsSymbolLayerUtils::decodePenJoinStyle( props[QStringLiteral( "joinstyle" )] ) );
3008  if ( props.contains( QStringLiteral( "horizontal_anchor_point" ) ) )
3009  m->setHorizontalAnchorPoint( QgsMarkerSymbolLayer::HorizontalAnchorPoint( props[ QStringLiteral( "horizontal_anchor_point" )].toInt() ) );
3010  if ( props.contains( QStringLiteral( "vertical_anchor_point" ) ) )
3011  m->setVerticalAnchorPoint( QgsMarkerSymbolLayer::VerticalAnchorPoint( props[ QStringLiteral( "vertical_anchor_point" )].toInt() ) );
3012 
3013  m->restoreOldDataDefinedProperties( props );
3014 
3015  return m;
3016 }
3017 
3019 {
3020  return QStringLiteral( "FontMarker" );
3021 }
3022 
3024 {
3025  QColor brushColor = mColor;
3026  QColor penColor = mStrokeColor;
3027 
3028  brushColor.setAlphaF( mColor.alphaF() * context.opacity() );
3029  penColor.setAlphaF( mStrokeColor.alphaF() * context.opacity() );
3030 
3031  mBrush = QBrush( brushColor );
3032  mPen = QPen( penColor );
3033  mPen.setJoinStyle( mPenJoinStyle );
3034  mPen.setWidthF( context.renderContext().convertToPainterUnits( mStrokeWidth, mStrokeWidthUnit, mStrokeWidthMapUnitScale ) );
3035 
3036  mFont = QFont( mFontFamily );
3037  if ( !mFontStyle.isEmpty() )
3038  {
3039  mFont.setStyleName( QgsFontUtils::translateNamedStyle( mFontStyle ) );
3040  }
3041 
3042  const double sizePixels = context.renderContext().convertToPainterUnits( mSize, mSizeUnit, mSizeMapUnitScale );
3043  mNonZeroFontSize = !qgsDoubleNear( sizePixels, 0.0 );
3044  // if a non zero, but small pixel size results, round up to 2 pixels so that a "dot" is at least visible
3045  // (if we set a <=1 pixel size here Qt will reset the font to a default size, leading to much too large symbols)
3046  mFont.setPixelSize( std::max( 2, static_cast< int >( std::round( sizePixels ) ) ) );
3047  mFontMetrics.reset( new QFontMetrics( mFont ) );
3048 #if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
3049  mChrWidth = mFontMetrics->width( mString );
3050 #else
3051  mChrWidth = mFontMetrics->horizontalAdvance( mString );
3052 #endif
3053  mChrOffset = QPointF( mChrWidth / 2.0, -mFontMetrics->ascent() / 2.0 );
3054  mOrigSize = mSize; // save in case the size would be data defined
3055 
3056  // use caching only when not using a data defined character
3060  if ( mUseCachedPath )
3061  {
3062  QPointF chrOffset = mChrOffset;
3063  double chrWidth;
3064  QString charToRender = characterToRender( context, chrOffset, chrWidth );
3065  mCachedPath = QPainterPath();
3066  mCachedPath.addText( -chrOffset.x(), -chrOffset.y(), mFont, charToRender );
3067  }
3068 }
3069 
3071 {
3072  Q_UNUSED( context )
3073 }
3074 
3075 QString QgsFontMarkerSymbolLayer::characterToRender( QgsSymbolRenderContext &context, QPointF &charOffset, double &charWidth )
3076 {
3077  charOffset = mChrOffset;
3078  QString stringToRender = mString;
3080  {
3081  context.setOriginalValueVariable( mString );
3083  if ( stringToRender != mString )
3084  {
3085 #if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
3086  charWidth = mFontMetrics->width( stringToRender );
3087 #else
3088  charWidth = mFontMetrics->horizontalAdvance( stringToRender );
3089 #endif
3090  charOffset = QPointF( charWidth / 2.0, -mFontMetrics->ascent() / 2.0 );
3091  }
3092  }
3093  return stringToRender;
3094 }
3095 
3096 void QgsFontMarkerSymbolLayer::calculateOffsetAndRotation( QgsSymbolRenderContext &context,
3097  double scaledSize,
3098  bool &hasDataDefinedRotation,
3099  QPointF &offset,
3100  double &angle ) const
3101 {
3102  //offset
3103  double offsetX = 0;
3104  double offsetY = 0;
3105  markerOffset( context, scaledSize, scaledSize, offsetX, offsetY );
3106  offset = QPointF( offsetX, offsetY );
3107 
3108  //angle
3109  bool ok = true;
3110  angle = mAngle + mLineAngle;
3112  {
3113  context.setOriginalValueVariable( angle );
3115 
3116  // If the expression evaluation was not successful, fallback to static value
3117  if ( !ok )
3118  angle = mAngle + mLineAngle;
3119  }
3120 
3121  hasDataDefinedRotation = context.renderHints() & QgsSymbol::DynamicRotation;
3122  if ( hasDataDefinedRotation )
3123  {
3124  // For non-point markers, "dataDefinedRotation" means following the
3125  // shape (shape-data defined). For them, "field-data defined" does
3126  // not work at all. TODO: if "field-data defined" ever gets implemented
3127  // we'll need a way to distinguish here between the two, possibly
3128  // using another flag in renderHints()
3129  const QgsFeature *f = context.feature();
3130  if ( f )
3131  {
3132  if ( f->hasGeometry() && f->geometry().type() == QgsWkbTypes::PointGeometry )
3133  {
3134  const QgsMapToPixel &m2p = context.renderContext().mapToPixel();
3135  angle += m2p.mapRotation();
3136  }
3137  }
3138  }
3139 
3140  if ( angle )
3142 }
3143 
3144 double QgsFontMarkerSymbolLayer::calculateSize( QgsSymbolRenderContext &context )
3145 {
3146  double scaledSize = mSize;
3147  bool hasDataDefinedSize = mDataDefinedProperties.isActive( QgsSymbolLayer::PropertySize );
3148 
3149  bool ok = true;
3150  if ( hasDataDefinedSize )
3151  {
3152  context.setOriginalValueVariable( mSize );
3154  }
3155 
3156  if ( hasDataDefinedSize && ok )
3157  {
3158  switch ( mScaleMethod )
3159  {
3160  case QgsSymbol::ScaleArea:
3161  scaledSize = std::sqrt( scaledSize );
3162  break;
3164  break;
3165  }
3166  }
3167  return scaledSize;
3168 }
3169 
3171 {
3172  QPainter *p = context.renderContext().painter();
3173  if ( !p || !mNonZeroFontSize )
3174  return;
3175 
3176  QTransform transform;
3177 
3178  bool ok;
3179  QColor brushColor = mColor;
3181  {
3184  }
3185  brushColor = context.selected() ? context.renderContext().selectionColor() : brushColor;
3186  if ( !SELECTION_IS_OPAQUE )
3187  {
3188  brushColor.setAlphaF( brushColor.alphaF() * context.opacity() );
3189  }
3190  mBrush.setColor( brushColor );
3191 
3192  QColor penColor = mStrokeColor;
3194  {
3197  }
3198  penColor.setAlphaF( penColor.alphaF() * context.opacity() );
3199 
3200  double penWidth = context.renderContext().convertToPainterUnits( mStrokeWidth, mStrokeWidthUnit, mStrokeWidthMapUnitScale );
3202  {
3203  context.setOriginalValueVariable( mStrokeWidth );
3205  if ( ok )
3206  {
3207  penWidth = context.renderContext().convertToPainterUnits( strokeWidth, mStrokeWidthUnit, mStrokeWidthMapUnitScale );
3208  }
3209  }
3210 
3212  {
3215  if ( ok )
3216  {
3217  mPen.setJoinStyle( QgsSymbolLayerUtils::decodePenJoinStyle( style ) );
3218  }
3219  }
3220 
3221  QgsScopedQPainterState painterState( p );
3222  p->setBrush( mBrush );
3223  if ( !qgsDoubleNear( penWidth, 0.0 ) )
3224  {
3225  mPen.setColor( penColor );
3226  mPen.setWidthF( penWidth );
3227  p->setPen( mPen );
3228  }
3229  else
3230  {
3231  p->setPen( Qt::NoPen );
3232  }
3233 
3235  {
3236  context.setOriginalValueVariable( mFontFamily );
3238  mFont.setFamily( ok ? fontFamily : mFontFamily );
3239  }
3241  {
3242  context.setOriginalValueVariable( mFontStyle );
3244  mFont.setStyleName( QgsFontUtils::translateNamedStyle( ok ? fontStyle : mFontStyle ) );
3245  }
3247  {
3248  mFontMetrics.reset( new QFontMetrics( mFont ) );
3249  }
3250 
3251  QPointF chrOffset = mChrOffset;
3252  double chrWidth;
3253  QString charToRender = characterToRender( context, chrOffset, chrWidth );
3254 
3255  double sizeToRender = calculateSize( context );
3256 
3257  bool hasDataDefinedRotation = false;
3258  QPointF offset;
3259  double angle = 0;
3260  calculateOffsetAndRotation( context, sizeToRender, hasDataDefinedRotation, offset, angle );
3261 
3262  p->translate( point.x() + offset.x(), point.y() + offset.y() );
3263 
3264  if ( !qgsDoubleNear( angle, 0.0 ) )
3265  transform.rotate( angle );
3266 
3267  if ( !qgsDoubleNear( sizeToRender, mOrigSize ) )
3268  {
3269  double s = sizeToRender / mOrigSize;
3270  transform.scale( s, s );
3271  }
3272 
3273  if ( mUseCachedPath )
3274  {
3275  p->drawPath( transform.map( mCachedPath ) );
3276  }
3277  else
3278  {
3279  QPainterPath path;
3280  path.addText( -chrOffset.x(), -chrOffset.y(), mFont, charToRender );
3281  p->drawPath( transform.map( path ) );
3282  }
3283 }
3284 
3286 {
3287  QgsStringMap props;
3288  props[QStringLiteral( "font" )] = mFontFamily;
3289  props[QStringLiteral( "font_style" )] = mFontStyle;
3290  props[QStringLiteral( "chr" )] = mString;
3291  props[QStringLiteral( "size" )] = QString::number( mSize );
3292  props[QStringLiteral( "size_unit" )] = QgsUnitTypes::encodeUnit( mSizeUnit );
3293  props[QStringLiteral( "size_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mSizeMapUnitScale );
3294  props[QStringLiteral( "color" )] = QgsSymbolLayerUtils::encodeColor( mColor );
3295  props[QStringLiteral( "outline_color" )] = QgsSymbolLayerUtils::encodeColor( mStrokeColor );
3296  props[QStringLiteral( "outline_width" )] = QString::number( mStrokeWidth );
3297  props[QStringLiteral( "outline_width_unit" )] = QgsUnitTypes::encodeUnit( mStrokeWidthUnit );
3298  props[QStringLiteral( "outline_width_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mStrokeWidthMapUnitScale );
3299  props[QStringLiteral( "joinstyle" )] = QgsSymbolLayerUtils::encodePenJoinStyle( mPenJoinStyle );
3300  props[QStringLiteral( "angle" )] = QString::number( mAngle );
3301  props[QStringLiteral( "offset" )] = QgsSymbolLayerUtils::encodePoint( mOffset );
3302  props[QStringLiteral( "offset_unit" )] = QgsUnitTypes::encodeUnit( mOffsetUnit );
3303  props[QStringLiteral( "offset_map_unit_scale" )] = QgsSymbolLayerUtils::encodeMapUnitScale( mOffsetMapUnitScale );
3304  props[QStringLiteral( "horizontal_anchor_point" )] = QString::number( mHorizontalAnchorPoint );
3305  props[QStringLiteral( "vertical_anchor_point" )] = QString::number( mVerticalAnchorPoint );
3306  return props;
3307 }
3308 
3310 {
3311  QgsFontMarkerSymbolLayer *m = new QgsFontMarkerSymbolLayer( mFontFamily, mString, mSize, mColor, mAngle );
3312  m->setFontStyle( mFontStyle );
3313  m->setStrokeColor( mStrokeColor );
3314  m->setStrokeWidth( mStrokeWidth );
3315  m->setStrokeWidthUnit( mStrokeWidthUnit );
3316  m->setStrokeWidthMapUnitScale( mStrokeWidthMapUnitScale );
3317  m->setPenJoinStyle( mPenJoinStyle );
3318  m->setOffset( mOffset );
3319  m->setOffsetUnit( mOffsetUnit );
3321  m->setSizeUnit( mSizeUnit );
3326  copyPaintEffect( m );
3327  return m;
3328 }
3329 
3330 void QgsFontMarkerSymbolLayer::writeSldMarker( QDomDocument &doc, QDomElement &element, const QgsStringMap &props ) const
3331 {
3332  // <Graphic>
3333  QDomElement graphicElem = doc.createElement( QStringLiteral( "se:Graphic" ) );
3334  element.appendChild( graphicElem );
3335 
3336  QString fontPath = QStringLiteral( "ttf://%1" ).arg( mFontFamily );
3337  int markIndex = !mString.isEmpty() ? mString.at( 0 ).unicode() : 0;
3339  QgsSymbolLayerUtils::externalMarkerToSld( doc, graphicElem, fontPath, QStringLiteral( "ttf" ), &markIndex, mColor, size );
3340 
3341  // <Rotation>
3342  QString angleFunc;
3343  bool ok;
3344  double angle = props.value( QStringLiteral( "angle" ), QStringLiteral( "0" ) ).toDouble( &ok );
3345  if ( !ok )
3346  {
3347  angleFunc = QStringLiteral( "%1 + %2" ).arg( props.value( QStringLiteral( "angle" ), QStringLiteral( "0" ) ) ).arg( mAngle );
3348  }
3349  else if ( !qgsDoubleNear( angle + mAngle, 0.0 ) )
3350  {
3351  angleFunc = QString::number( angle + mAngle );
3352  }
3353  QgsSymbolLayerUtils::createRotationElement( doc, graphicElem, angleFunc );
3354 
3355  // <Displacement>
3358 }
3359 
3361 {
3362  QPointF chrOffset = mChrOffset;
3363  double chrWidth = mChrWidth;
3364  //calculate width of rendered character
3365  ( void )characterToRender( context, chrOffset, chrWidth );
3366 
3367  if ( !mFontMetrics )
3368  mFontMetrics.reset( new QFontMetrics( mFont ) );
3369 
3370  double scaledSize = calculateSize( context );
3371  if ( !qgsDoubleNear( scaledSize, mOrigSize ) )
3372  {
3373  chrWidth *= scaledSize / mOrigSize;
3374  }
3375 
3376  bool hasDataDefinedRotation = false;
3377  QPointF offset;
3378  double angle = 0;
3379  calculateOffsetAndRotation( context, scaledSize, hasDataDefinedRotation, offset, angle );
3380  scaledSize = context.renderContext().convertToPainterUnits( scaledSize, mSizeUnit, mSizeMapUnitScale );
3381 
3382  QMatrix transform;
3383 
3384  // move to the desired position
3385  transform.translate( point.x() + offset.x(), point.y() + offset.y() );
3386 
3387  if ( !qgsDoubleNear( angle, 0.0 ) )
3388  transform.rotate( angle );
3389 
3390  QRectF symbolBounds = transform.mapRect( QRectF( -chrWidth / 2.0,
3391  -scaledSize / 2.0,
3392  chrWidth,
3393  scaledSize ) );
3394  return symbolBounds;
3395 }
3396 
3398 {
3399  QgsDebugMsgLevel( QStringLiteral( "Entered." ), 4 );
3400 
3401  QDomElement graphicElem = element.firstChildElement( QStringLiteral( "Graphic" ) );
3402  if ( graphicElem.isNull() )
3403  return nullptr;
3404 
3405  QString name, format;
3406  QColor color;
3407  double size;
3408  int chr;
3409 
3410  if ( !QgsSymbolLayerUtils::externalMarkerFromSld( graphicElem, name, format, chr, color, size ) )
3411  return nullptr;
3412 
3413  if ( !name.startsWith( QLatin1String( "ttf://" ) ) || format != QLatin1String( "ttf" ) )
3414  return nullptr;
3415 
3416  QString fontFamily = name.mid( 6 );
3417 
3418  double angle = 0.0;
3419  QString angleFunc;
3420  if ( QgsSymbolLayerUtils::rotationFromSldElement( graphicElem, angleFunc ) )
3421  {
3422  bool ok;
3423  double d = angleFunc.toDouble( &ok );
3424  if ( ok )
3425  angle = d;
3426  }
3427 
3428  QPointF offset;
3430 
3431  QString uom = element.attribute( QStringLiteral( "uom" ) );
3435 
3437  m->setOutputUnit( QgsUnitTypes::RenderUnit::RenderPixels );
3438  m->setAngle( angle );
3439  m->setOffset( offset );
3440  return m;
3441 }
3442 
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:1411
QgsFilledMarkerSymbolLayer::setColor
void setColor(const QColor &c) override
The fill color.
Definition: qgsmarkersymbollayer.cpp:1697
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:725
QgsRasterMarkerSymbolLayer::mFixedAspectRatio
double mFixedAspectRatio
The marker fixed aspect ratio.
Definition: qgsmarkersymbollayer.h:776
QgsMarkerSymbolLayer::setSizeUnit
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the symbol's size.
Definition: qgssymbollayer.h:670
qgssvgcache.h
QgsSvgMarkerSymbolLayer::mapUnitScale
QgsMapUnitScale mapUnitScale() const override
Definition: qgsmarkersymbollayer.cpp:2264
QgsSvgMarkerSymbolLayer::layerType
QString layerType() const override
Returns a string that represents this layer type.
Definition: qgsmarkersymbollayer.cpp:1945
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:770
QgsMarkerSymbolLayer::VerticalAnchorPoint
VerticalAnchorPoint
Symbol vertical anchor points.
Definition: qgssymbollayer.h:595
QgsRasterMarkerSymbolLayer::renderPoint
void renderPoint(QPointF point, QgsSymbolRenderContext &context) override
Renders a marker at the specified point.
Definition: qgsmarkersymbollayer.cpp:2662
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:318
QgsSymbolLayer::mColor
QColor mColor
Definition: qgssymbollayer.h:527
QgsRenderContext::setPainterFlagsUsingContext
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
Definition: qgsrendercontext.cpp:143
QgsFilledMarkerSymbolLayer
Filled marker symbol layer, consisting of a shape which is rendered using a QgsFillSymbol.
Definition: qgsmarkersymbollayer.h:427
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:325
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:661
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:2467
QgsRasterMarkerSymbolLayer::opacity
double opacity() const
Returns the marker opacity.
Definition: qgsmarkersymbollayer.h:712
QgsUnitTypes::RenderUnit
RenderUnit
Rendering size units.
Definition: qgsunittypes.h:167
QgsSimpleMarkerSymbolLayer::strokeStyle
Qt::PenStyle strokeStyle() const
Returns the marker's stroke style (e.g., solid, dashed, etc)
Definition: qgsmarkersymbollayer.h: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:1028
QgsDxfExport
Definition: qgsdxfexport.h:63
QgsMarkerSymbolLayer::mSizeMapUnitScale
QgsMapUnitScale mSizeMapUnitScale
Marker size map unit scale.
Definition: qgssymbollayer.h:873
QgsFontMarkerSymbolLayer::setStrokeWidth
void setStrokeWidth(double width)
Set's the marker's stroke width.
Definition: qgsmarkersymbollayer.h:910
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:2242
QgsRenderContext::expressionContext
QgsExpressionContext & expressionContext()
Gets the expression context.
Definition: qgsrendercontext.h:596
QgsFilledMarkerSymbolLayer::usedAttributes
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
Definition: qgsmarkersymbollayer.cpp:1680
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:2299
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:2434
QgsMarkerSymbolLayer::mapUnitScale
QgsMapUnitScale mapUnitScale() const override
Definition: qgssymbollayer.cpp:631
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:3285
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:2947
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:38
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:4563
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QgsSymbolRenderContext::feature
const QgsFeature * feature() const
Returns the current feature being rendered.
Definition: qgssymbol.h:802
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:1449
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:2354
QgsSymbolLayer::PropertyFontFamily
@ PropertyFontFamily
Font family.
Definition: qgssymbollayer.h:189
QgsSymbolLayer::setColor
virtual void setColor(const QColor &color)
The fill color.
Definition: qgssymbollayer.h:232
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:227
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:1621
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:796
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:1671
QgsMarkerSymbolLayer::setAngle
void setAngle(double angle)
Sets the rotation angle for the marker.
Definition: qgssymbollayer.h:627
QgsSymbolRenderContext::opacity
qreal opacity() const
Returns the opacity for the symbol.
Definition: qgssymbol.h:764
QgsRasterMarkerSymbolLayer::updateDefaultAspectRatio
double updateDefaultAspectRatio()
Calculates the default marker aspect ratio between width and height.
Definition: qgsmarkersymbollayer.cpp:2647
QgsMarkerSymbolLayer::scaleMethod
QgsSymbol::ScaleMethod scaleMethod() const
Returns the method to use for scaling the marker's size.
Definition: qgssymbollayer.h:708
QgsSvgMarkerSymbolLayer::setPath
void setPath(const QString &path)
Set the marker SVG path.
Definition: qgsmarkersymbollayer.cpp:1867
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:216
QgsFilledMarkerSymbolLayer::create
static QgsSymbolLayer * create(const QgsStringMap &properties=QgsStringMap())
Creates a new QgsFilledMarkerSymbolLayer.
Definition: qgsmarkersymbollayer.cpp:1555
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:1062
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:67
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:2864
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:447
QgsRenderContext
Contains information about the context of a rendering operation.
Definition: qgsrendercontext.h:58
QgsSymbol::ScaleDiameter
@ ScaleDiameter
Calculate scale by the diameter.
Definition: qgssymbol.h:99
DEFAULT_RASTERMARKER_SIZE
#define DEFAULT_RASTERMARKER_SIZE
Definition: qgsmarkersymbollayer.h:643
QgsSymbolLayerUtils::multiplyImageOpacity
static void multiplyImageOpacity(QImage *image, qreal opacity)
Multiplies opacity of image pixel values with a (global) transparency value.
Definition: qgssymbollayerutils.cpp:3737
QgsSymbolLayer::SELECTION_IS_OPAQUE
static const bool SELECTION_IS_OPAQUE
Whether styles for selected features ignore symbol alpha.
Definition: qgssymbollayer.h:537
QgsSimpleMarkerSymbolLayer::setColor
void setColor(const QColor &color) override
The fill color.
Definition: qgsmarkersymbollayer.cpp:1518
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:881
QgsUnitTypes::RenderMillimeters
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:168
DEFAULT_FONTMARKER_FONT
#define DEFAULT_FONTMARKER_FONT
Definition: qgsmarkersymbollayer.h:790
QgsMarkerSymbolLayer
Abstract base class for marker symbol layers.
Definition: qgssymbollayer.h:582
QgsSimpleMarkerSymbolLayer::ogrFeatureStyle
QString ogrFeatureStyle(double mmScaleFactor, double mapUnitScaleFactor) const override
Definition: qgsmarkersymbollayer.cpp:1134
qgsdxfpaintdevice.h
QgsRasterMarkerSymbolLayer::setOpacity
void setOpacity(double opacity)
Set the marker opacity.
Definition: qgsmarkersymbollayer.h:719
QgsSymbol::ScaleMethod
ScaleMethod
Scale method.
Definition: qgssymbol.h:97
QgsFontMarkerSymbolLayer::setStrokeColor
void setStrokeColor(const QColor &color) override
Set stroke color.
Definition: qgsmarkersymbollayer.h:888
QgsSymbolLayerUtils::encodePenStyle
static QString encodePenStyle(Qt::PenStyle style)
Definition: qgssymbollayerutils.cpp:141
QgsRasterMarkerSymbolLayer::mapUnitScale
QgsMapUnitScale mapUnitScale() const override
Definition: qgsmarkersymbollayer.cpp:2905
DEFAULT_SIMPLEMARKER_JOINSTYLE
#define DEFAULT_SIMPLEMARKER_JOINSTYLE
Definition: qgsmarkersymbollayer.h:26
QgsSymbol
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:64
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:2910
QgsMarkerSymbolLayer::setMapUnitScale
void setMapUnitScale(const QgsMapUnitScale &scale) override
Definition: qgssymbollayer.cpp:625
QgsSimpleMarkerSymbolLayer::clone
QgsSimpleMarkerSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
Definition: qgsmarkersymbollayer.cpp:1086
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:4007
QgsMarkerSymbolLayer::mSizeUnit
QgsUnitTypes::RenderUnit mSizeUnit
Marker size unit.
Definition: qgssymbollayer.h:871
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:406
QgsRenderContext::scaleFactor
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
Definition: qgsrendercontext.h:333
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:2258
QgsSimpleMarkerSymbolLayer::create
static QgsSymbolLayer * create(const QgsStringMap &properties=QgsStringMap())
Creates a new QgsSimpleMarkerSymbolLayer.
Definition: qgsmarkersymbollayer.cpp:717
QgsFilledMarkerSymbolLayer::startRender
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
Definition: qgsmarkersymbollayer.cpp:1603
QgsFilledMarkerSymbolLayer::color
QColor color() const override
The fill color.
Definition: qgsmarkersymbollayer.cpp:1704
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:2883
QgsSvgMarkerSymbolLayer::createFromSld
static QgsSymbolLayer * createFromSld(QDomElement &element)
Definition: qgsmarkersymbollayer.cpp:2304
QgsMarkerSymbolLayer::mVerticalAnchorPoint
VerticalAnchorPoint mVerticalAnchorPoint
Vertical anchor point.
Definition: qgssymbollayer.h:885
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:557
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:871
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:2398
QgsFontMarkerSymbolLayer::clone
QgsFontMarkerSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
Definition: qgsmarkersymbollayer.cpp:3309
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:1855
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:877
QgsFilledMarkerSymbolLayer::stopRender
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
Definition: qgsmarkersymbollayer.cpp:1613
QgsSymbolRenderContext::selected
bool selected() const
Returns true if symbols should be rendered using the selected symbol coloring and style.
Definition: qgssymbol.h:777
QgsSymbolLayerUtils::createDisplacementElement
static void createDisplacementElement(QDomDocument &doc, QDomElement &element, QPointF offset)
Definition: qgssymbollayerutils.cpp:2522
qt_defaultDpiY
Q_GUI_EXPORT int qt_defaultDpiY()
QgsMarkerSymbolLayer::mSize
double mSize
Marker size.
Definition: qgssymbollayer.h:869
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:695
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:761
QgsSimpleMarkerSymbolLayer::color
QColor color() const override
The fill color.
Definition: qgsmarkersymbollayer.cpp:1530
QgsFontMarkerSymbolLayer::stopRender
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
Definition: qgsmarkersymbollayer.cpp:3070
QgsMarkerSymbolLayer::HorizontalAnchorPoint
HorizontalAnchorPoint
Symbol horizontal anchor points.
Definition: qgssymbollayer.h:587
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:610
QgsSvgMarkerSymbolLayer::updateDefaultAspectRatio
double updateDefaultAspectRatio()
Calculates the default marker aspect ratio between width and height.
Definition: qgsmarkersymbollayer.cpp:1915
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:931
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:1479
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:477
QgsSimpleMarkerSymbolLayerBase
Abstract base class for simple marker symbol layers.
Definition: qgsmarkersymbollayer.h:44
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:53
QgsRenderContext::forceVectorOutput
bool forceVectorOutput() const
Returns true if rendering operations should use vector operations instead of any faster raster shortc...
Definition: qgsrendercontext.cpp:246
QgsSimpleMarkerSymbolLayerBase::Shape
Shape
Marker symbol shapes.
Definition: qgsmarkersymbollayer.h:49
QgsSvgMarkerSymbolLayer::mHasFillParam
bool mHasFillParam
Definition: qgsmarkersymbollayer.h:627
QgsDxfExport::mapUnits
QgsUnitTypes::DistanceUnit mapUnits() const
Retrieve map units.
Definition: qgsdxfexport.cpp:245
QgsDxfPaintDevice
A paint device for drawing into dxf files.
Definition: qgsdxfpaintdevice.h:38
QgsSimpleMarkerSymbolLayer::fillColor
QColor fillColor() const override
Gets fill color.
Definition: qgsmarkersymbollayer.h:251
QgsRasterMarkerSymbolLayer::setMapUnitScale
void setMapUnitScale(const QgsMapUnitScale &scale) override
Definition: qgsmarkersymbollayer.cpp:2900
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:2248
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:1950
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:738
QgsSimpleMarkerSymbolLayerBase::RightHalfTriangle
@ RightHalfTriangle
Right half of triangle.
Definition: qgsmarkersymbollayer.h:71
QgsSvgMarkerSymbolLayer::mStrokeWidthMapUnitScale
QgsMapUnitScale mStrokeWidthMapUnitScale
Definition: qgsmarkersymbollayer.h:632
QgsSymbolRenderContext::fields
QgsFields fields() const
Fields of the layer.
Definition: qgssymbol.h:827
QgsRasterMarkerSymbolLayer::layerType
QString layerType() const override
Returns a string that represents this layer type.
Definition: qgsmarkersymbollayer.cpp:2657
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:82
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:3397
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:3018
QgsMapToPixel::mapRotation
double mapRotation() const
Returns current map rotation in degrees (clockwise)
Definition: qgsmaptopixel.cpp:158
QgsSvgMarkerSymbolLayer::setPreservedAspectRatio
bool setPreservedAspectRatio(bool par)
Set preserved the marker aspect ratio between width and height.
Definition: qgsmarkersymbollayer.cpp:1930
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:792
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:4428
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:1257
QgsSimpleMarkerSymbolLayer
Simple marker symbol layer, consisting of a rendered shape with solid fill color and an stroke.
Definition: qgsmarkersymbollayer.h:199
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:791
QgsFilledMarkerSymbolLayer::subSymbol
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
Definition: qgsmarkersymbollayer.cpp:1652
QgsSvgMarkerSymbolLayer::mStrokeWidth
double mStrokeWidth
Definition: qgsmarkersymbollayer.h:629
QgsSvgMarkerSymbolLayer
Definition: qgsmarkersymbollayer.h:483
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:410
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:616
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:2615
QgsFilledMarkerSymbolLayer::layerType
QString layerType() const override
Returns a string that represents this layer type.
Definition: qgsmarkersymbollayer.cpp:1598
QgsApplication::imageCache
static QgsImageCache * imageCache()
Returns the application's image cache, used for caching resampled versions of raster images.
Definition: qgsapplication.cpp:2183
QgsRasterMarkerSymbolLayer::calculateAspectRatio
double calculateAspectRatio(QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedAspectRatio) const
Calculates the marker aspect ratio between width and height.
Definition: qgsmarkersymbollayer.cpp:2789
qgsrendercontext.h
QgsRasterMarkerSymbolLayer::setPath
void setPath(const QString &path)
Set the marker raster image path.
Definition: qgsmarkersymbollayer.cpp:2627
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:794
QgsSvgMarkerSymbolLayer::create
static QgsSymbolLayer * create(const QgsStringMap &properties=QgsStringMap())
Definition: qgsmarkersymbollayer.cpp:1761
QgsSimpleMarkerSymbolLayer::prepareCache
bool prepareCache(QgsSymbolRenderContext &context)
Prepares cache image.
Definition: qgsmarkersymbollayer.cpp:880
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:818
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:971
QgsRasterMarkerSymbolLayer
Raster marker symbol layer class.
Definition: qgsmarkersymbollayer.h:653
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:1961
QgsSvgMarkerSymbolLayer::mStrokeWidthUnit
QgsUnitTypes::RenderUnit mStrokeWidthUnit
Definition: qgsmarkersymbollayer.h:631
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:718
QgsRasterMarkerSymbolLayer::mPath
QString mPath
Definition: qgsmarkersymbollayer.h:770
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:2221
QgsMapUnitScale
Struct for storing maximum and minimum scales for measurements in map units.
Definition: qgsmapunitscale.h:38
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:2198
QgsScopedQPainterState
Scoped object for saving and restoring a QPainter object's state.
Definition: qgsrendercontext.h:1120
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:530
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:268
QgsRingSequence
QVector< QgsPointSequence > QgsRingSequence
Definition: qgsabstractgeometry.h:50
QgsRasterMarkerSymbolLayer::path
QString path() const
Returns the marker raster image path.
Definition: qgsmarkersymbollayer.h:698
QgsMarkerSymbolLayer::setOffsetUnit
void setOffsetUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the symbol's offset.
Definition: qgssymbollayer.h:736
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:294
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:2178
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:247
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:2552
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:3330
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:789
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:2273
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:1470
QgsRenderContext::selectionColor
QColor selectionColor() const
Returns the color to use when rendering selected features.
Definition: qgsrendercontext.h:390
QgsSimpleMarkerSymbolLayer::createFromSld
static QgsSymbolLayer * createFromSld(QDomElement &element)
Creates a new QgsSimpleMarkerSymbolLayer from an SLD XML element.
Definition: qgsmarkersymbollayer.cpp:1196
QgsSvgMarkerSymbolLayer::calculateAspectRatio
double calculateAspectRatio(QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedAspectRatio) const
Calculates the marker aspect ratio between width and height.
Definition: qgsmarkersymbollayer.cpp:2118
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:1105
QgsMarkerSymbolLayer::setOffsetMapUnitScale
void setOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the symbol's offset.
Definition: qgssymbollayer.h:753
QgsStringMap
QMap< QString, QString > QgsStringMap
Definition: qgis.h:758
QgsSimpleMarkerSymbolLayer::setMapUnitScale
void setMapUnitScale(const QgsMapUnitScale &scale) override
Definition: qgsmarkersymbollayer.cpp:1464
QgsMarkerSymbolLayer::mOffset
QPointF mOffset
Marker offset.
Definition: qgssymbollayer.h:875
QgsWkbTypes::PointGeometry
@ PointGeometry
Definition: qgswkbtypes.h:142
QgsFontMarkerSymbolLayer::create
static QgsSymbolLayer * create(const QgsStringMap &properties=QgsStringMap())
Creates a new QgsFontMarkerSymbolLayer from a property map (see properties())
Definition: qgsmarkersymbollayer.cpp:2964
QgsFontMarkerSymbolLayer::fontStyle
QString fontStyle() const
Returns the font style for the associated font which will be used to render the point.
Definition: qgsmarkersymbollayer.h:863
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:1657
QgsMarkerSymbolLayer::mHorizontalAnchorPoint
HorizontalAnchorPoint mHorizontalAnchorPoint
Horizontal anchor point.
Definition: qgssymbollayer.h:883
QgsSvgMarkerSymbolLayer::stopRender
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
Definition: qgsmarkersymbollayer.cpp:1956
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:1643
QgsSimpleMarkerSymbolLayerBase::QuarterCircle
@ QuarterCircle
Quarter circle (top left quarter)
Definition: qgsmarkersymbollayer.h:67
QgsPointSequence
QVector< QgsPoint > QgsPointSequence
Definition: qgsabstractgeometry.h:46
QgsPropertyCollection::value
QVariant value(int key, const QgsExpressionContext &context, const QVariant &defaultValue=QVariant()) const override
Returns the calculated value of the property with the specified key from within the collection.
Definition: qgspropertycollection.cpp:228
c
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
Definition: porting_processing.dox:1
QgsSimpleMarkerSymbolLayerBase::mPath
QPainterPath mPath
Painter path representing shape. If mPolygon is empty then the shape is stored in mPath.
Definition: qgsmarkersymbollayer.h:175
QgsMapToPixel
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:38
QgsDxfExport::writeFilledCircle
void writeFilledCircle(const QString &layer, const QColor &color, const QgsPoint &pt, double radius)
Write filled circle (as hatch)
Definition: qgsdxfexport.cpp: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:1688
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:199
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:813
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:3941
QgsMarkerSymbolLayer::mLineAngle
double mLineAngle
Line rotation angle (see setLineAngle() for details)
Definition: qgssymbollayer.h:867
QgsFontMarkerSymbolLayer
Definition: qgsmarkersymbollayer.h:803
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:3170
QgsSymbolLayerUtils::rotationFromSldElement
static bool rotationFromSldElement(QDomElement &element, QString &rotationFunc)
Definition: qgssymbollayerutils.cpp:2491
QgsSymbolLayerUtils::encodeScaleMethod
static QString encodeScaleMethod(QgsSymbol::ScaleMethod scaleMethod)
Definition: qgssymbollayerutils.cpp:713
QgsSymbolLayer::PropertyAngle
@ PropertyAngle
Symbol angle.
Definition: qgssymbollayer.h:133
QgsFillSymbol
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
Definition: qgssymbol.h:1234
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:280
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:281
QgsRasterMarkerSymbolLayer::mOpacity
double mOpacity
The marker default opacity.
Definition: qgsmarkersymbollayer.h:772
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
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:2481
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:571
QgsMarkerSymbolLayer::offset
QPointF offset() const
Returns the marker's offset, which is the horizontal and vertical displacement which the rendered mar...
Definition: qgssymbollayer.h:727
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:687
QgsMarkerSymbolLayer::setVerticalAnchorPoint
void setVerticalAnchorPoint(VerticalAnchorPoint v)
Sets the vertical anchor point for positioning the symbol.
Definition: qgssymbollayer.h:787
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:1747
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:656
DEFAULT_FONTMARKER_JOINSTYLE
#define DEFAULT_FONTMARKER_JOINSTYLE
Definition: qgsmarkersymbollayer.h:795
QgsMarkerSymbolLayer::mAngle
double mAngle
Marker rotation angle, in degrees clockwise from north.
Definition: qgssymbollayer.h:865
QgsRenderContext::RenderSymbolPreview
@ RenderSymbolPreview
The render is for a symbol preview only and map based properties may not be available,...
Definition: qgsrendercontext.h:83
QgsSymbolLayerUtils::encodePenJoinStyle
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
Definition: qgssymbollayerutils.cpp:173
QgsFeature
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:56
QgsFillSymbol::createSimple
static QgsFillSymbol * createSimple(const QgsStringMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties.
Definition: qgssymbol.cpp:1481
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:1549
QgsSymbolRenderContext::renderContext
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
Definition: qgssymbol.h:721
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:709
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:822
QgsFontMarkerSymbolLayer::setStrokeWidthMapUnitScale
void setStrokeWidthMapUnitScale(const QgsMapUnitScale &scale)
Sets the stroke width map unit scale.
Definition: qgsmarkersymbollayer.h:953
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:2236
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:179
QgsSimpleMarkerSymbolLayer::outputUnit
QgsUnitTypes::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
Definition: qgsmarkersymbollayer.cpp:1455
QgsSymbol::ScaleArea
@ ScaleArea
Calculate scale by the area.
Definition: qgssymbol.h:98
DEFAULT_FONTMARKER_COLOR
#define DEFAULT_FONTMARKER_COLOR
Definition: qgsmarkersymbollayer.h:793
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:2348
QgsRasterMarkerSymbolLayer::mDefaultAspectRatio
double mDefaultAspectRatio
The marker default aspect ratio.
Definition: qgsmarkersymbollayer.h:774
QgsSymbolLayerUtils::displacementFromSldElement
static bool displacementFromSldElement(QDomElement &element, QPointF &offset)
Definition: qgssymbollayerutils.cpp:2557
QgsPropertyCollection::isActive
bool isActive(int key) const override
Returns true if the collection contains an active property with the specified key.
Definition: qgspropertycollection.cpp:268
QgsSymbolLayerUtils::externalMarkerToSld
static void externalMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &path, const QString &format, int *markIndex=nullptr, const QColor &color=QColor(), double size=-1)
Definition: qgssymbollayerutils.cpp:2324
QgsGeometry::type
QgsWkbTypes::GeometryType type
Definition: qgsgeometry.h:127
QgsSimpleMarkerSymbolLayerBase::encodeShape
static QString encodeShape(QgsSimpleMarkerSymbolLayerBase::Shape shape)
Encodes a shape to its string representation.
Definition: qgsmarkersymbollayer.cpp:352
QgsSimpleMarkerSymbolLayerBase::EquilateralTriangle
@ EquilateralTriangle
Equilateral triangle.
Definition: qgsmarkersymbollayer.h:55
QgsMarkerSymbolLayer::mOffsetMapUnitScale
QgsMapUnitScale mOffsetMapUnitScale
Offset map unit scale.
Definition: qgssymbollayer.h:879
QgsSimpleMarkerSymbolLayerBase::shapeToPolygon
bool shapeToPolygon(Shape shape, QPolygonF &polygon) const
Creates a polygon representing the specified shape.
Definition: qgsmarkersymbollayer.cpp:411
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:402
QgsFontMarkerSymbolLayer::startRender
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
Definition: qgsmarkersymbollayer.cpp:3023
QgsPathResolver
Resolves relative paths into absolute paths and vice versa.
Definition: qgspathresolver.h:32
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:633
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:848
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:2563
QgsSimpleMarkerSymbolLayerBase::calculateSize
double calculateSize(QgsSymbolRenderContext &context, bool &hasDataDefinedSize) const
Calculates the desired size of the marker, considering data defined size overrides.
Definition: qgsmarkersymbollayer.cpp:628
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:2633
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:899
QgsSvgMarkerSymbolLayer::mStrokeColor
QColor mStrokeColor
Definition: qgsmarkersymbollayer.h:628
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:1243
QgsRenderContext::flags
Flags flags() const
Returns combination of flags used for rendering.
Definition: qgsrendercontext.cpp:187
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:3360
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:644
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