QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgssymbol.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgssymbol.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 <QColor>
17 #include <QImage>
18 #include <QPainter>
19 #include <QSize>
20 #include <QSvgGenerator>
21 
22 #include <cmath>
23 #include <map>
24 #include <random>
25 
26 #include "qgssymbol.h"
27 #include "qgssymbollayer.h"
28 
29 #include "qgslinesymbollayer.h"
30 #include "qgsmarkersymbollayer.h"
31 #include "qgsfillsymbollayer.h"
34 #include "qgslogger.h"
35 #include "qgsrendercontext.h" // for bigSymbolPreview
36 #include "qgsproject.h"
38 #include "qgsstyle.h"
39 #include "qgspainteffect.h"
40 #include "qgseffectstack.h"
41 #include "qgsvectorlayer.h"
42 #include "qgsfeature.h"
43 #include "qgsgeometry.h"
44 #include "qgsmultipoint.h"
45 #include "qgsgeometrycollection.h"
46 #include "qgslinestring.h"
47 #include "qgspolygon.h"
48 #include "qgsclipper.h"
49 #include "qgsproperty.h"
50 #include "qgscolorschemeregistry.h"
51 #include "qgsapplication.h"
54 #include "qgslegendpatchshape.h"
55 #include "qgsgeos.h"
56 #include "qgsmarkersymbol.h"
57 #include "qgslinesymbol.h"
58 #include "qgsfillsymbol.h"
59 
60 QgsPropertiesDefinition QgsSymbol::sPropertyDefinitions;
61 
62 Q_NOWARN_DEPRECATED_PUSH // because of deprecated mLayer
64  : mType( type )
65  , mLayers( layers )
66 {
67 
68  // check they're all correct symbol layers
69  for ( int i = 0; i < mLayers.count(); i++ )
70  {
71  if ( !mLayers.at( i ) )
72  {
73  mLayers.removeAt( i-- );
74  }
75  else if ( !mLayers.at( i )->isCompatibleWithSymbol( this ) )
76  {
77  delete mLayers.at( i );
78  mLayers.removeAt( i-- );
79  }
80  }
81 }
83 
84 QPolygonF QgsSymbol::_getLineString( QgsRenderContext &context, const QgsCurve &curve, bool clipToExtent )
85 {
86  if ( curve.is3D() )
87  return _getLineString3d( context, curve, clipToExtent );
88  else
89  return _getLineString2d( context, curve, clipToExtent );
90 }
91 
92 QPolygonF QgsSymbol::_getLineString3d( QgsRenderContext &context, const QgsCurve &curve, bool clipToExtent )
93 {
94  const unsigned int nPoints = curve.numPoints();
95 
97  const QgsMapToPixel &mtp = context.mapToPixel();
98  QVector< double > pointsX;
99  QVector< double > pointsY;
100  QVector< double > pointsZ;
101 
102  // apply clipping for large lines to achieve a better rendering performance
103  if ( clipToExtent && nPoints > 1 && !( context.flags() & Qgis::RenderContextFlag::ApplyClipAfterReprojection ) )
104  {
105  const QgsRectangle e = context.extent();
106  const double cw = e.width() / 10;
107  const double ch = e.height() / 10;
108  const QgsBox3d clipRect( e.xMinimum() - cw, e.yMinimum() - ch, -HUGE_VAL, e.xMaximum() + cw, e.yMaximum() + ch, HUGE_VAL ); // TODO also need to be clipped according to z axis
109 
110  const QgsLineString *lineString = nullptr;
111  if ( const QgsLineString *ls = qgsgeometry_cast< const QgsLineString * >( &curve ) )
112  {
113  lineString = ls;
114  }
115  else
116  {
117  std::unique_ptr< QgsLineString > segmentized;
118  segmentized.reset( qgsgeometry_cast< QgsLineString * >( curve.segmentize( ) ) );
119  lineString = segmentized.get();
120  }
121 
122  QgsClipper::clipped3dLine( lineString->xVector(), lineString->yVector(), lineString->zVector(), pointsX, pointsY, pointsZ, clipRect );
123  }
124  else
125  {
126  // clone...
127  if ( const QgsLineString *ls = qgsgeometry_cast<const QgsLineString *>( &curve ) )
128  {
129  pointsX = ls->xVector();
130  pointsY = ls->yVector();
131  pointsZ = ls->zVector();
132  }
133  else
134  {
135  std::unique_ptr< QgsLineString > segmentized;
136  segmentized.reset( qgsgeometry_cast< QgsLineString * >( curve.segmentize( ) ) );
137 
138  pointsX = segmentized->xVector();
139  pointsY = segmentized->yVector();
140  pointsZ = segmentized->zVector();
141  }
142  }
143 
144  // transform the points to screen coordinates
145  if ( ct.isValid() )
146  {
147  //create x, y arrays
148  const int nVertices = pointsX.size();
149 
150  try
151  {
152  ct.transformCoords( nVertices, pointsX.data(), pointsY.data(), pointsZ.data(), Qgis::TransformDirection::Forward );
153  }
154  catch ( QgsCsException & )
155  {
156  // we don't abort the rendering here, instead we remove any invalid points and just plot those which ARE valid
157  }
158  }
159 
160  // remove non-finite points, e.g. infinite or NaN points caused by reprojecting errors
161  {
162  const int size = pointsX.size();
163 
164  const double *xIn = pointsX.data();
165  const double *yIn = pointsY.data();
166  const double *zIn = pointsZ.data();
167  double *xOut = pointsX.data();
168  double *yOut = pointsY.data();
169  double *zOut = pointsZ.data();
170  int outSize = 0;
171  for ( int i = 0; i < size; ++i )
172  {
173  if ( std::isfinite( *xIn ) && std::isfinite( *yIn ) && std::isfinite( *zIn ) )
174  {
175  *xOut++ = *xIn++;
176  *yOut++ = *yIn++;
177  *zOut++ = *zIn++;
178  outSize++;
179  }
180  else
181  {
182  xIn++;
183  yIn++;
184  zIn++;
185  }
186  }
187  pointsX.resize( outSize );
188  pointsY.resize( outSize );
189  pointsZ.resize( outSize );
190  }
191 
192  if ( clipToExtent && nPoints > 1 && context.flags() & Qgis::RenderContextFlag::ApplyClipAfterReprojection )
193  {
194  // early clipping was not possible, so we have to apply it here after transformation
195  const QgsRectangle e = context.mapExtent();
196  const double cw = e.width() / 10;
197  const double ch = e.height() / 10;
198  const QgsBox3d clipRect( e.xMinimum() - cw, e.yMinimum() - ch, -HUGE_VAL, e.xMaximum() + cw, e.yMaximum() + ch, HUGE_VAL ); // TODO also need to be clipped according to z axis
199 
200  QVector< double > tempX;
201  QVector< double > tempY;
202  QVector< double > tempZ;
203  QgsClipper::clipped3dLine( pointsX, pointsY, pointsZ, tempX, tempY, tempZ, clipRect );
204  pointsX = tempX;
205  pointsY = tempY;
206  pointsZ = tempZ;
207  }
208 
209  const int polygonSize = pointsX.size();
210  QPolygonF out( polygonSize );
211  const double *x = pointsX.constData();
212  const double *y = pointsY.constData();
213  QPointF *dest = out.data();
214  for ( int i = 0; i < polygonSize; ++i )
215  {
216  double screenX = *x++;
217  double screenY = *y++;
218  mtp.transformInPlace( screenX, screenY );
219  *dest++ = QPointF( screenX, screenY );
220  }
221 
222  return out;
223 }
224 
225 QPolygonF QgsSymbol::_getLineString2d( QgsRenderContext &context, const QgsCurve &curve, bool clipToExtent )
226 {
227  const unsigned int nPoints = curve.numPoints();
228 
230  const QgsMapToPixel &mtp = context.mapToPixel();
231  QPolygonF pts;
232 
233  // apply clipping for large lines to achieve a better rendering performance
234  if ( clipToExtent && nPoints > 1 && !( context.flags() & Qgis::RenderContextFlag::ApplyClipAfterReprojection ) )
235  {
236  const QgsRectangle e = context.extent();
237  const double cw = e.width() / 10;
238  const double ch = e.height() / 10;
239  const QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch );
240  pts = QgsClipper::clippedLine( curve, clipRect );
241  }
242  else
243  {
244  pts = curve.asQPolygonF();
245  }
246 
247  // transform the QPolygonF to screen coordinates
248  if ( ct.isValid() )
249  {
250  try
251  {
252  ct.transformPolygon( pts );
253  }
254  catch ( QgsCsException & )
255  {
256  // we don't abort the rendering here, instead we remove any invalid points and just plot those which ARE valid
257  }
258  }
259 
260  // remove non-finite points, e.g. infinite or NaN points caused by reprojecting errors
261  pts.erase( std::remove_if( pts.begin(), pts.end(),
262  []( const QPointF point )
263  {
264  return !std::isfinite( point.x() ) || !std::isfinite( point.y() );
265  } ), pts.end() );
266 
267  if ( clipToExtent && nPoints > 1 && context.flags() & Qgis::RenderContextFlag::ApplyClipAfterReprojection )
268  {
269  // early clipping was not possible, so we have to apply it here after transformation
270  const QgsRectangle e = context.mapExtent();
271  const double cw = e.width() / 10;
272  const double ch = e.height() / 10;
273  const QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch );
274  pts = QgsClipper::clippedLine( pts, clipRect );
275  }
276 
277  QPointF *ptr = pts.data();
278  for ( int i = 0; i < pts.size(); ++i, ++ptr )
279  {
280  mtp.transformInPlace( ptr->rx(), ptr->ry() );
281  }
282 
283  return pts;
284 }
285 
286 
287 QPolygonF QgsSymbol::_getPolygonRing( QgsRenderContext &context, const QgsCurve &curve, const bool clipToExtent, const bool isExteriorRing, const bool correctRingOrientation )
288 {
289  if ( curve.is3D() )
290  return _getPolygonRing3d( context, curve, clipToExtent, isExteriorRing, correctRingOrientation );
291  else
292  return _getPolygonRing2d( context, curve, clipToExtent, isExteriorRing, correctRingOrientation );
293 }
294 
295 QPolygonF QgsSymbol::_getPolygonRing3d( QgsRenderContext &context, const QgsCurve &curve, const bool clipToExtent, const bool isExteriorRing, const bool correctRingOrientation )
296 {
297  const QgsCoordinateTransform ct = context.coordinateTransform();
298  const QgsMapToPixel &mtp = context.mapToPixel();
299 
300  QVector< double > pointsX;
301  QVector< double > pointsY;
302  QVector< double > pointsZ;
303 
304  if ( curve.numPoints() < 1 )
305  return QPolygonF();
306 
307  bool reverseRing = false;
308  if ( correctRingOrientation )
309  {
310  // ensure consistent polygon ring orientation
311  if ( ( isExteriorRing && curve.orientation() != Qgis::AngularDirection::Clockwise ) || ( !isExteriorRing && curve.orientation() != Qgis::AngularDirection::CounterClockwise ) )
312  {
313  reverseRing = true;
314  }
315  }
316 
317  //clip close to view extent, if needed
318  if ( clipToExtent && !( context.flags() & Qgis::RenderContextFlag::ApplyClipAfterReprojection ) && !context.extent().contains( curve.boundingBox() ) )
319  {
320  const QgsRectangle e = context.extent();
321  const double cw = e.width() / 10;
322  const double ch = e.height() / 10;
323  const QgsBox3d clipRect( e.xMinimum() - cw, e.yMinimum() - ch, -HUGE_VAL, e.xMaximum() + cw, e.yMaximum() + ch, HUGE_VAL ); // TODO also need to be clipped according to z axis
324 
325  const QgsLineString *lineString = nullptr;
326  std::unique_ptr< QgsLineString > segmentized;
327  if ( const QgsLineString *ls = qgsgeometry_cast< const QgsLineString * >( &curve ) )
328  {
329  lineString = ls;
330  }
331  else
332  {
333  segmentized.reset( qgsgeometry_cast< QgsLineString * >( curve.segmentize( ) ) );
334  lineString = segmentized.get();
335  }
336 
337  pointsX = lineString->xVector();
338  pointsY = lineString->yVector();
339  pointsZ = lineString->zVector();
340 
341  QgsClipper::trimPolygon( pointsX, pointsY, pointsZ, clipRect );
342  }
343  else
344  {
345  // clone...
346  if ( const QgsLineString *ls = qgsgeometry_cast<const QgsLineString *>( &curve ) )
347  {
348  pointsX = ls->xVector();
349  pointsY = ls->yVector();
350  pointsZ = ls->zVector();
351  }
352  else
353  {
354  std::unique_ptr< QgsLineString > segmentized;
355  segmentized.reset( qgsgeometry_cast< QgsLineString * >( curve.segmentize( ) ) );
356 
357  pointsX = segmentized->xVector();
358  pointsY = segmentized->yVector();
359  pointsZ = segmentized->zVector();
360  }
361  }
362 
363  if ( reverseRing )
364  {
365  std::reverse( pointsX.begin(), pointsX.end() );
366  std::reverse( pointsY.begin(), pointsY.end() );
367  std::reverse( pointsZ.begin(), pointsZ.end() );
368  }
369 
370  //transform the QPolygonF to screen coordinates
371  if ( ct.isValid() )
372  {
373  const int nVertices = pointsX.size();
374  try
375  {
376  ct.transformCoords( nVertices, pointsX.data(), pointsY.data(), pointsZ.data(), Qgis::TransformDirection::Forward );
377  }
378  catch ( QgsCsException & )
379  {
380  // we don't abort the rendering here, instead we remove any invalid points and just plot those which ARE valid
381  }
382  }
383 
384  // remove non-finite points, e.g. infinite or NaN points caused by reprojecting errors
385  {
386  const int size = pointsX.size();
387 
388  const double *xIn = pointsX.data();
389  const double *yIn = pointsY.data();
390  const double *zIn = pointsZ.data();
391  double *xOut = pointsX.data();
392  double *yOut = pointsY.data();
393  double *zOut = pointsZ.data();
394  int outSize = 0;
395  for ( int i = 0; i < size; ++i )
396  {
397  if ( std::isfinite( *xIn ) && std::isfinite( *yIn ) && std::isfinite( *zIn ) )
398  {
399  *xOut++ = *xIn++;
400  *yOut++ = *yIn++;
401  *zOut++ = *zIn++;
402  outSize++;
403  }
404  else
405  {
406  xIn++;
407  yIn++;
408  zIn++;
409  }
410  }
411  pointsX.resize( outSize );
412  pointsY.resize( outSize );
413  pointsZ.resize( outSize );
414  }
415 
416  if ( clipToExtent && context.flags() & Qgis::RenderContextFlag::ApplyClipAfterReprojection && !context.mapExtent().contains( curve.boundingBox() ) )
417  {
418  // early clipping was not possible, so we have to apply it here after transformation
419  const QgsRectangle e = context.mapExtent();
420  const double cw = e.width() / 10;
421  const double ch = e.height() / 10;
422  const QgsBox3d clipRect( e.xMinimum() - cw, e.yMinimum() - ch, -HUGE_VAL, e.xMaximum() + cw, e.yMaximum() + ch, HUGE_VAL ); // TODO also need to be clipped according to z axis
423 
424  QgsClipper::trimPolygon( pointsX, pointsY, pointsZ, clipRect );
425  }
426 
427  const int polygonSize = pointsX.size();
428  QPolygonF out( polygonSize );
429  const double *x = pointsX.constData();
430  const double *y = pointsY.constData();
431  QPointF *dest = out.data();
432  for ( int i = 0; i < polygonSize; ++i )
433  {
434  double screenX = *x++;
435  double screenY = *y++;
436  mtp.transformInPlace( screenX, screenY );
437  *dest++ = QPointF( screenX, screenY );
438  }
439 
440  if ( !out.empty() && !out.isClosed() )
441  out << out.at( 0 );
442 
443  return out;
444 }
445 
446 
447 QPolygonF QgsSymbol::_getPolygonRing2d( QgsRenderContext &context, const QgsCurve &curve, const bool clipToExtent, const bool isExteriorRing, const bool correctRingOrientation )
448 {
449  const QgsCoordinateTransform ct = context.coordinateTransform();
450  const QgsMapToPixel &mtp = context.mapToPixel();
451 
452  QPolygonF poly = curve.asQPolygonF();
453 
454  if ( curve.numPoints() < 1 )
455  return QPolygonF();
456 
457  if ( correctRingOrientation )
458  {
459  // ensure consistent polygon ring orientation
460  if ( isExteriorRing && curve.orientation() != Qgis::AngularDirection::Clockwise )
461  std::reverse( poly.begin(), poly.end() );
462  else if ( !isExteriorRing && curve.orientation() != Qgis::AngularDirection::CounterClockwise )
463  std::reverse( poly.begin(), poly.end() );
464  }
465 
466  //clip close to view extent, if needed
467  if ( clipToExtent && !( context.flags() & Qgis::RenderContextFlag::ApplyClipAfterReprojection ) && !context.extent().contains( poly.boundingRect() ) )
468  {
469  const QgsRectangle e = context.extent();
470  const double cw = e.width() / 10;
471  const double ch = e.height() / 10;
472  const QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch );
473  QgsClipper::trimPolygon( poly, clipRect );
474  }
475 
476  //transform the QPolygonF to screen coordinates
477  if ( ct.isValid() )
478  {
479  try
480  {
481  ct.transformPolygon( poly );
482  }
483  catch ( QgsCsException & )
484  {
485  // we don't abort the rendering here, instead we remove any invalid points and just plot those which ARE valid
486  }
487  }
488 
489  // remove non-finite points, e.g. infinite or NaN points caused by reprojecting errors
490  poly.erase( std::remove_if( poly.begin(), poly.end(),
491  []( const QPointF point )
492  {
493  return !std::isfinite( point.x() ) || !std::isfinite( point.y() );
494  } ), poly.end() );
495 
496  if ( clipToExtent && context.flags() & Qgis::RenderContextFlag::ApplyClipAfterReprojection && !context.mapExtent().contains( poly.boundingRect() ) )
497  {
498  // early clipping was not possible, so we have to apply it here after transformation
499  const QgsRectangle e = context.mapExtent();
500  const double cw = e.width() / 10;
501  const double ch = e.height() / 10;
502  const QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch );
503  QgsClipper::trimPolygon( poly, clipRect );
504  }
505 
506  QPointF *ptr = poly.data();
507  for ( int i = 0; i < poly.size(); ++i, ++ptr )
508  {
509  mtp.transformInPlace( ptr->rx(), ptr->ry() );
510  }
511 
512  if ( !poly.empty() && !poly.isClosed() )
513  poly << poly.at( 0 );
514 
515  return poly;
516 }
517 
518 void QgsSymbol::_getPolygon( QPolygonF &pts, QVector<QPolygonF> &holes, QgsRenderContext &context, const QgsPolygon &polygon, const bool clipToExtent, const bool correctRingOrientation )
519 {
520  holes.clear();
521 
522  pts = _getPolygonRing( context, *polygon.exteriorRing(), clipToExtent, true, correctRingOrientation );
523  const int ringCount = polygon.numInteriorRings();
524  holes.reserve( ringCount );
525  for ( int idx = 0; idx < ringCount; idx++ )
526  {
527  const QPolygonF hole = _getPolygonRing( context, *( polygon.interiorRing( idx ) ), clipToExtent, false, correctRingOrientation );
528  if ( !hole.isEmpty() )
529  holes.append( hole );
530  }
531 }
532 
534 {
535  switch ( type )
536  {
538  return QObject::tr( "Marker" );
540  return QObject::tr( "Line" );
542  return QObject::tr( "Fill" );
544  return QObject::tr( "Hybrid" );
545  }
546  return QString();
547 }
548 
550 {
551  switch ( type )
552  {
556  return Qgis::SymbolType::Line;
558  return Qgis::SymbolType::Fill;
562  }
564 }
565 
567 {
568  QgsSymbol::initPropertyDefinitions();
569  return sPropertyDefinitions;
570 }
571 
573 {
574  // delete all symbol layers (we own them, so it's okay)
575  qDeleteAll( mLayers );
576 }
577 
579 {
580  if ( mLayers.empty() )
581  {
583  }
584 
585  QgsSymbolLayerList::const_iterator it = mLayers.constBegin();
586 
587  QgsUnitTypes::RenderUnit unit = ( *it )->outputUnit();
588 
589  for ( ; it != mLayers.constEnd(); ++it )
590  {
591  if ( ( *it )->outputUnit() != unit )
592  {
594  }
595  }
596  return unit;
597 }
598 
600 {
601  if ( mLayers.empty() )
602  {
603  return false;
604  }
605 
606  for ( const QgsSymbolLayer *layer : mLayers )
607  {
608  if ( layer->usesMapUnits() )
609  {
610  return true;
611  }
612  }
613  return false;
614 }
615 
617 {
618  if ( mLayers.empty() )
619  {
620  return QgsMapUnitScale();
621  }
622 
623  QgsSymbolLayerList::const_iterator it = mLayers.constBegin();
624  if ( it == mLayers.constEnd() )
625  return QgsMapUnitScale();
626 
627  QgsMapUnitScale scale = ( *it )->mapUnitScale();
628  ++it;
629 
630  for ( ; it != mLayers.constEnd(); ++it )
631  {
632  if ( ( *it )->mapUnitScale() != scale )
633  {
634  return QgsMapUnitScale();
635  }
636  }
637  return scale;
638 }
639 
641 {
642  const auto constMLayers = mLayers;
643  for ( QgsSymbolLayer *layer : constMLayers )
644  {
645  layer->setOutputUnit( u );
646  }
647 }
648 
649 void QgsSymbol::setMapUnitScale( const QgsMapUnitScale &scale ) const
650 {
651  const auto constMLayers = mLayers;
652  for ( QgsSymbolLayer *layer : constMLayers )
653  {
654  layer->setMapUnitScale( scale );
655  }
656 }
657 
659 {
660  return mAnimationSettings;
661 }
662 
664 {
665  return mAnimationSettings;
666 }
667 
669 {
670  mAnimationSettings = settings;
671 }
672 
674 {
675  std::unique_ptr< QgsSymbol > s;
676 
677  // override global default if project has a default for this type
678  switch ( geomType )
679  {
681  s.reset( QgsProject::instance()->styleSettings()->defaultSymbol( Qgis::SymbolType::Marker ) );
682  break;
684  s.reset( QgsProject::instance()->styleSettings()->defaultSymbol( Qgis::SymbolType::Line ) );
685  break;
687  s.reset( QgsProject::instance()->styleSettings()->defaultSymbol( Qgis::SymbolType::Fill ) );
688  break;
689  default:
690  break;
691  }
692 
693  // if no default found for this type, get global default (as previously)
694  if ( !s )
695  {
696  switch ( geomType )
697  {
699  s = std::make_unique< QgsMarkerSymbol >();
700  break;
702  s = std::make_unique< QgsLineSymbol >();
703  break;
705  s = std::make_unique< QgsFillSymbol >();
706  break;
707  default:
708  QgsDebugMsg( QStringLiteral( "unknown layer's geometry type" ) );
709  return nullptr;
710  }
711  }
712 
713  // set opacity
714  s->setOpacity( QgsProject::instance()->styleSettings()->defaultSymbolOpacity() );
715 
716  // set random color, it project prefs allow
717  if ( QgsProject::instance()->styleSettings()->randomizeDefaultSymbolColor() )
718  {
719  s->setColor( QgsApplication::colorSchemeRegistry()->fetchRandomStyleColor() );
720  }
721 
722  return s.release();
723 }
724 
726 {
727  return mLayers.value( layer );
728 }
729 
730 const QgsSymbolLayer *QgsSymbol::symbolLayer( int layer ) const
731 {
732  return mLayers.value( layer );
733 }
734 
736 {
737  if ( index < 0 || index > mLayers.count() ) // can be added also after the last index
738  return false;
739 
740  if ( !layer || !layer->isCompatibleWithSymbol( this ) )
741  return false;
742 
743  mLayers.insert( index, layer );
744  return true;
745 }
746 
747 
749 {
750  if ( !layer || !layer->isCompatibleWithSymbol( this ) )
751  return false;
752 
753  mLayers.append( layer );
754  return true;
755 }
756 
757 
759 {
760  if ( index < 0 || index >= mLayers.count() )
761  return false;
762 
763  delete mLayers.at( index );
764  mLayers.removeAt( index );
765  return true;
766 }
767 
768 
770 {
771  if ( index < 0 || index >= mLayers.count() )
772  return nullptr;
773 
774  return mLayers.takeAt( index );
775 }
776 
777 
779 {
780  QgsSymbolLayer *oldLayer = mLayers.value( index );
781 
782  if ( oldLayer == layer )
783  return false;
784 
785  if ( !layer || !layer->isCompatibleWithSymbol( this ) )
786  return false;
787 
788  delete oldLayer; // first delete the original layer
789  mLayers[index] = layer; // set new layer
790  return true;
791 }
792 
793 
794 void QgsSymbol::startRender( QgsRenderContext &context, const QgsFields &fields )
795 {
796  Q_ASSERT_X( !mStarted, "startRender", "Rendering has already been started for this symbol instance!" );
797  mStarted = true;
798 
799  mSymbolRenderContext.reset( new QgsSymbolRenderContext( context, QgsUnitTypes::RenderUnknownUnit, mOpacity, false, mRenderHints, nullptr, fields ) );
800 
801  // Why do we need a copy here ? Is it to make sure the symbol layer rendering does not mess with the symbol render context ?
802  // Or is there another profound reason ?
803  QgsSymbolRenderContext symbolContext( context, QgsUnitTypes::RenderUnknownUnit, mOpacity, false, mRenderHints, nullptr, fields );
804 
805  std::unique_ptr< QgsExpressionContextScope > scope( QgsExpressionContextUtils::updateSymbolScope( this, new QgsExpressionContextScope() ) );
806 
808  {
809  const long long mapFrameNumber = context.currentFrame();
810  double animationTimeSeconds = 0;
811  if ( mapFrameNumber >= 0 && context.frameRate() > 0 )
812  {
813  // render is part of an animation, so we base the calculated frame on that
814  animationTimeSeconds = mapFrameNumber / context.frameRate();
815  }
816  else
817  {
818  // render is outside of animation, so base the calculated frame on the current epoch
819  animationTimeSeconds = QDateTime::currentMSecsSinceEpoch() / 1000.0;
820  }
821 
822  const long long symbolFrame = static_cast< long long >( std::floor( animationTimeSeconds * mAnimationSettings.frameRate() ) );
823  scope->setVariable( QStringLiteral( "symbol_frame" ), symbolFrame, true );
824  }
825 
826  mSymbolRenderContext->setExpressionContextScope( scope.release() );
827 
828  mDataDefinedProperties.prepare( context.expressionContext() );
829 
830  const auto constMLayers = mLayers;
831  for ( QgsSymbolLayer *layer : constMLayers )
832  {
833  if ( !layer->enabled() || !context.isSymbolLayerEnabled( layer ) )
834  continue;
835 
836  layer->prepareExpressions( symbolContext );
837  layer->prepareMasks( symbolContext );
838  layer->startRender( symbolContext );
839  }
840 }
841 
843 {
844  Q_ASSERT_X( mStarted, "startRender", "startRender was not called for this symbol instance!" );
845  mStarted = false;
846 
847  Q_UNUSED( context )
848  if ( mSymbolRenderContext )
849  {
850  const auto constMLayers = mLayers;
851  for ( QgsSymbolLayer *layer : constMLayers )
852  {
853  if ( !layer->enabled() || !context.isSymbolLayerEnabled( layer ) )
854  continue;
855 
856  layer->stopRender( *mSymbolRenderContext );
857  }
858  }
859 
860  mSymbolRenderContext.reset( nullptr );
861 
863  mLayer = nullptr;
865 }
866 
867 void QgsSymbol::setColor( const QColor &color ) const
868 {
869  const auto constMLayers = mLayers;
870  for ( QgsSymbolLayer *layer : constMLayers )
871  {
872  if ( !layer->isLocked() )
873  layer->setColor( color );
874  }
875 }
876 
877 QColor QgsSymbol::color() const
878 {
879  for ( const QgsSymbolLayer *layer : mLayers )
880  {
881  // return color of the first unlocked layer
882  if ( !layer->isLocked() )
883  {
884  const QColor layerColor = layer->color();
885  if ( layerColor.isValid() )
886  return layerColor;
887  }
888  }
889  return QColor( 0, 0, 0 );
890 }
891 
892 void QgsSymbol::drawPreviewIcon( QPainter *painter, QSize size, QgsRenderContext *customContext, bool selected, const QgsExpressionContext *expressionContext, const QgsLegendPatchShape *patchShape )
893 {
894  QgsRenderContext *context = customContext;
895  std::unique_ptr< QgsRenderContext > tempContext;
896  if ( !context )
897  {
898  tempContext.reset( new QgsRenderContext( QgsRenderContext::fromQPainter( painter ) ) );
899  context = tempContext.get();
901  }
902 
903  const bool prevForceVector = context->forceVectorOutput();
904  context->setForceVectorOutput( true );
905 
906  const double opacity = expressionContext ? dataDefinedProperties().valueAsDouble( QgsSymbol::PropertyOpacity, *expressionContext, mOpacity ) : mOpacity;
907 
908  QgsSymbolRenderContext symbolContext( *context, QgsUnitTypes::RenderUnknownUnit, opacity, false, mRenderHints, nullptr );
909  symbolContext.setSelected( selected );
910  switch ( mType )
911  {
914  break;
917  break;
920  break;
923  break;
924  }
925 
926  if ( patchShape )
927  symbolContext.setPatchShape( *patchShape );
928 
929  if ( !customContext && expressionContext )
930  {
931  context->setExpressionContext( *expressionContext );
932  }
933  else if ( !customContext )
934  {
935  // if no render context was passed, build a minimal expression context
936  QgsExpressionContext expContext;
938  context->setExpressionContext( expContext );
939  }
940 
941  for ( QgsSymbolLayer *layer : std::as_const( mLayers ) )
942  {
943  if ( !layer->enabled() || ( customContext && !customContext->isSymbolLayerEnabled( layer ) ) )
944  continue;
945 
947  {
948  // line symbol layer would normally draw just a line
949  // so we override this case to force it to draw a polygon stroke
950  QgsLineSymbolLayer *lsl = dynamic_cast<QgsLineSymbolLayer *>( layer );
951  if ( lsl )
952  {
953  // from QgsFillSymbolLayer::drawPreviewIcon() -- would be nicer to add the
954  // symbol type to QgsSymbolLayer::drawPreviewIcon so this logic could be avoided!
955 
956  // hmm... why was this using size -1 ??
957  const QSizeF targetSize = QSizeF( size.width() - 1, size.height() - 1 );
958 
959  const QList< QList< QPolygonF > > polys = patchShape ? patchShape->toQPolygonF( Qgis::SymbolType::Fill, targetSize )
961 
962  lsl->startRender( symbolContext );
963  QgsPaintEffect *effect = lsl->paintEffect();
964 
965  std::unique_ptr< QgsEffectPainter > effectPainter;
966  if ( effect && effect->enabled() )
967  effectPainter = std::make_unique< QgsEffectPainter >( symbolContext.renderContext(), effect );
968 
969  for ( const QList< QPolygonF > &poly : polys )
970  {
971  QVector< QPolygonF > rings;
972  rings.reserve( poly.size() );
973  for ( int i = 1; i < poly.size(); ++i )
974  rings << poly.at( i );
975  lsl->renderPolygonStroke( poly.value( 0 ), &rings, symbolContext );
976  }
977 
978  effectPainter.reset();
979  lsl->stopRender( symbolContext );
980  }
981  }
982  else
983  layer->drawPreviewIcon( symbolContext, size );
984  }
985 
986  context->setForceVectorOutput( prevForceVector );
987 }
988 
989 void QgsSymbol::exportImage( const QString &path, const QString &format, QSize size )
990 {
991  if ( format.compare( QLatin1String( "svg" ), Qt::CaseInsensitive ) == 0 )
992  {
993  QSvgGenerator generator;
994  generator.setFileName( path );
995  generator.setSize( size );
996  generator.setViewBox( QRect( 0, 0, size.height(), size.height() ) );
997 
998  QPainter painter( &generator );
999  drawPreviewIcon( &painter, size );
1000  painter.end();
1001  }
1002  else
1003  {
1004  QImage image = asImage( size );
1005  image.save( path );
1006  }
1007 }
1008 
1009 QImage QgsSymbol::asImage( QSize size, QgsRenderContext *customContext )
1010 {
1011  QImage image( size, QImage::Format_ARGB32_Premultiplied );
1012  image.fill( 0 );
1013 
1014  QPainter p( &image );
1015  p.setRenderHint( QPainter::Antialiasing );
1016  p.setRenderHint( QPainter::SmoothPixmapTransform );
1017 
1018  drawPreviewIcon( &p, size, customContext );
1019 
1020  return image;
1021 }
1022 
1023 
1024 QImage QgsSymbol::bigSymbolPreviewImage( QgsExpressionContext *expressionContext, Qgis::SymbolPreviewFlags flags )
1025 {
1026  QImage preview( QSize( 100, 100 ), QImage::Format_ARGB32_Premultiplied );
1027  preview.fill( 0 );
1028 
1029  QPainter p( &preview );
1030  p.setRenderHint( QPainter::Antialiasing );
1031  p.translate( 0.5, 0.5 ); // shift by half a pixel to avoid blurring due antialiasing
1032 
1034  {
1035  p.setPen( QPen( Qt::gray ) );
1036  p.drawLine( 0, 50, 100, 50 );
1037  p.drawLine( 50, 0, 50, 100 );
1038  }
1039 
1044  context.setPainterFlagsUsingContext( &p );
1045  if ( expressionContext )
1046  context.setExpressionContext( *expressionContext );
1047 
1048  context.setIsGuiPreview( true );
1049  startRender( context );
1050 
1051  if ( mType == Qgis::SymbolType::Line )
1052  {
1053  QPolygonF poly;
1054  poly << QPointF( 0, 50 ) << QPointF( 99, 50 );
1055  static_cast<QgsLineSymbol *>( this )->renderPolyline( poly, nullptr, context );
1056  }
1057  else if ( mType == Qgis::SymbolType::Fill )
1058  {
1059  QPolygonF polygon;
1060  polygon << QPointF( 20, 20 ) << QPointF( 80, 20 ) << QPointF( 80, 80 ) << QPointF( 20, 80 ) << QPointF( 20, 20 );
1061  static_cast<QgsFillSymbol *>( this )->renderPolygon( polygon, nullptr, nullptr, context );
1062  }
1063  else // marker
1064  {
1065  static_cast<QgsMarkerSymbol *>( this )->renderPoint( QPointF( 50, 50 ), nullptr, context );
1066  }
1067 
1068  stopRender( context );
1069  return preview;
1070 }
1071 
1072 QImage QgsSymbol::bigSymbolPreviewImage( QgsExpressionContext *expressionContext, int flags )
1073 {
1074  return bigSymbolPreviewImage( expressionContext, static_cast< Qgis::SymbolPreviewFlags >( flags ) );
1075 }
1076 
1077 QString QgsSymbol::dump() const
1078 {
1079  QString t;
1080  switch ( type() )
1081  {
1083  t = QStringLiteral( "MARKER" );
1084  break;
1086  t = QStringLiteral( "LINE" );
1087  break;
1089  t = QStringLiteral( "FILL" );
1090  break;
1091  default:
1092  Q_ASSERT( false && "unknown symbol type" );
1093  }
1094  QString s = QStringLiteral( "%1 SYMBOL (%2 layers) color %3" ).arg( t ).arg( mLayers.count() ).arg( QgsSymbolLayerUtils::encodeColor( color() ) );
1095 
1096  for ( QgsSymbolLayerList::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
1097  {
1098  // TODO:
1099  }
1100  return s;
1101 }
1102 
1103 void QgsSymbol::toSld( QDomDocument &doc, QDomElement &element, QVariantMap props ) const
1104 {
1105  props[ QStringLiteral( "alpha" )] = QString::number( opacity() );
1106  double scaleFactor = 1.0;
1107  props[ QStringLiteral( "uom" )] = QgsSymbolLayerUtils::encodeSldUom( outputUnit(), &scaleFactor );
1108  props[ QStringLiteral( "uomScale" )] = ( !qgsDoubleNear( scaleFactor, 1.0 ) ? qgsDoubleToString( scaleFactor ) : QString() );
1109 
1110  for ( QgsSymbolLayerList::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
1111  {
1112  ( *it )->toSld( doc, element, props );
1113  }
1114 }
1115 
1117 {
1118  QgsSymbolLayerList lst;
1119  for ( QgsSymbolLayerList::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
1120  {
1121  QgsSymbolLayer *layer = ( *it )->clone();
1122  layer->setLocked( ( *it )->isLocked() );
1123  layer->setRenderingPass( ( *it )->renderingPass() );
1124  layer->setEnabled( ( *it )->enabled() );
1125  lst.append( layer );
1126  }
1127  return lst;
1128 }
1129 
1130 void QgsSymbol::renderUsingLayer( QgsSymbolLayer *layer, QgsSymbolRenderContext &context, QgsWkbTypes::GeometryType geometryType, const QPolygonF *points, const QVector<QPolygonF> *rings )
1131 {
1132  Q_ASSERT( layer->type() == Qgis::SymbolType::Hybrid );
1133 
1134  if ( layer->dataDefinedProperties().hasActiveProperties() && !layer->dataDefinedProperties().valueAsBool( QgsSymbolLayer::PropertyLayerEnabled, context.renderContext().expressionContext(), true ) )
1135  return;
1136 
1137  QgsGeometryGeneratorSymbolLayer *generatorLayer = static_cast<QgsGeometryGeneratorSymbolLayer *>( layer );
1138 
1139  QgsPaintEffect *effect = generatorLayer->paintEffect();
1140  if ( effect && effect->enabled() )
1141  {
1142  QgsEffectPainter p( context.renderContext(), effect );
1143  generatorLayer->render( context, geometryType, points, rings );
1144  }
1145  else
1146  {
1147  generatorLayer->render( context, geometryType, points, rings );
1148  }
1149 }
1150 
1151 QSet<QString> QgsSymbol::usedAttributes( const QgsRenderContext &context ) const
1152 {
1153  // calling referencedFields() with ignoreContext=true because in our expression context
1154  // we do not have valid QgsFields yet - because of that the field names from expressions
1155  // wouldn't get reported
1156  QSet<QString> attributes = mDataDefinedProperties.referencedFields( context.expressionContext(), true );
1157  QgsSymbolLayerList::const_iterator sIt = mLayers.constBegin();
1158  for ( ; sIt != mLayers.constEnd(); ++sIt )
1159  {
1160  if ( *sIt )
1161  {
1162  attributes.unite( ( *sIt )->usedAttributes( context ) );
1163  }
1164  }
1165  return attributes;
1166 }
1167 
1169 {
1170  mDataDefinedProperties.setProperty( key, property );
1171 }
1172 
1174 {
1175  if ( mDataDefinedProperties.hasActiveProperties() )
1176  return true;
1177 
1178  for ( QgsSymbolLayer *layer : mLayers )
1179  {
1180  if ( layer->hasDataDefinedProperties() )
1181  return true;
1182  }
1183  return false;
1184 }
1185 
1187 {
1188  for ( QgsSymbolLayer *layer : mLayers )
1189  {
1190  if ( layer->canCauseArtifactsBetweenAdjacentTiles() )
1191  return true;
1192  }
1193  return false;
1194 }
1195 
1197 {
1199  mLayer = layer;
1201 }
1202 
1204 {
1206  return mLayer;
1208 }
1209 
1211 
1215 class ExpressionContextScopePopper
1216 {
1217  public:
1218 
1219  ExpressionContextScopePopper() = default;
1220 
1221  ~ExpressionContextScopePopper()
1222  {
1223  if ( context )
1224  context->popScope();
1225  }
1226 
1227  QgsExpressionContext *context = nullptr;
1228 };
1229 
1233 class GeometryRestorer
1234 {
1235  public:
1236  GeometryRestorer( QgsRenderContext &context )
1237  : mContext( context ),
1238  mGeometry( context.geometry() )
1239  {}
1240 
1241  ~GeometryRestorer()
1242  {
1243  mContext.setGeometry( mGeometry );
1244  }
1245 
1246  private:
1247  QgsRenderContext &mContext;
1248  const QgsAbstractGeometry *mGeometry;
1249 };
1251 
1252 void QgsSymbol::renderFeature( const QgsFeature &feature, QgsRenderContext &context, int layer, bool selected, bool drawVertexMarker, Qgis::VertexMarkerType currentVertexMarkerType, double currentVertexMarkerSize )
1253 {
1254  if ( context.renderingStopped() )
1255  return;
1256 
1257  const QgsGeometry geom = feature.geometry();
1258  if ( geom.isNull() )
1259  {
1260  return;
1261  }
1262 
1263  GeometryRestorer geomRestorer( context );
1264 
1265  bool usingSegmentizedGeometry = false;
1266  context.setGeometry( geom.constGet() );
1267 
1268  if ( geom.type() != QgsWkbTypes::PointGeometry && !geom.boundingBox().isNull() )
1269  {
1270  try
1271  {
1272  const QPointF boundsOrigin = _getPoint( context, QgsPoint( geom.boundingBox().xMinimum(), geom.boundingBox().yMinimum() ) );
1273  if ( std::isfinite( boundsOrigin.x() ) && std::isfinite( boundsOrigin.y() ) )
1274  context.setTextureOrigin( boundsOrigin );
1275  }
1276  catch ( QgsCsException & )
1277  {
1278 
1279  }
1280  }
1281 
1282  bool clippingEnabled = clipFeaturesToExtent();
1283  // do any symbol layers prevent feature clipping?
1284  for ( QgsSymbolLayer *layer : std::as_const( mLayers ) )
1285  {
1287  {
1288  clippingEnabled = false;
1289  break;
1290  }
1291  }
1292  if ( clippingEnabled && context.testFlag( Qgis::RenderContextFlag::RenderMapTile ) )
1293  {
1294  // If the "avoid artifacts between adjacent tiles" flag is set (RenderMapTile), then we'll force disable
1295  // the geometry clipping IF (and only if) this symbol can potentially have rendering artifacts when rendered as map tiles.
1296  // If the symbol won't have any artifacts anyway, then it's pointless and incredibly expensive to skip the clipping!
1298  {
1299  clippingEnabled = false;
1300  }
1301  }
1302  if ( context.extent().isEmpty() )
1303  clippingEnabled = false;
1304 
1305  mSymbolRenderContext->setGeometryPartCount( geom.constGet()->partCount() );
1306  mSymbolRenderContext->setGeometryPartNum( 1 );
1307 
1308  const bool needsExpressionContext = hasDataDefinedProperties();
1309  ExpressionContextScopePopper scopePopper;
1310  if ( mSymbolRenderContext->expressionContextScope() )
1311  {
1312  if ( needsExpressionContext )
1313  {
1314  // this is somewhat nasty - by appending this scope here it's now owned
1315  // by both mSymbolRenderContext AND context.expressionContext()
1316  // the RAII scopePopper is required to make sure it always has ownership transferred back
1317  // from context.expressionContext(), even if exceptions of other early exits occur in this
1318  // function
1319  context.expressionContext().appendScope( mSymbolRenderContext->expressionContextScope() );
1320  scopePopper.context = &context.expressionContext();
1321 
1322  QgsExpressionContextUtils::updateSymbolScope( this, mSymbolRenderContext->expressionContextScope() );
1323  mSymbolRenderContext->expressionContextScope()->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_PART_COUNT, mSymbolRenderContext->geometryPartCount(), true ) );
1324  mSymbolRenderContext->expressionContextScope()->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_PART_NUM, 1, true ) );
1325  }
1326  }
1327 
1328  // Collection of markers to paint, only used for no curve types.
1329  QPolygonF markers;
1330 
1331  QgsGeometry renderedBoundsGeom;
1332 
1333  // Step 1 - collect the set of painter coordinate geometries to render.
1334  // We do this upfront, because we only want to ever do this once, regardless how many symbol layers we need to render.
1335 
1336  struct PointInfo
1337  {
1338  QPointF renderPoint;
1339  const QgsPoint *originalGeometry = nullptr;
1340  };
1341  QVector< PointInfo > pointsToRender;
1342 
1343  struct LineInfo
1344  {
1345  QPolygonF renderLine;
1346  const QgsCurve *originalGeometry = nullptr;
1347  };
1348  QVector< LineInfo > linesToRender;
1349 
1350  struct PolygonInfo
1351  {
1352  QPolygonF renderExterior;
1353  QVector< QPolygonF > renderRings;
1354  const QgsCurvePolygon *originalGeometry = nullptr;
1355  int originalPartIndex = 0;
1356  };
1357  QVector< PolygonInfo > polygonsToRender;
1358 
1359  std::function< void ( const QgsAbstractGeometry *, int partIndex )> getPartGeometry;
1360  getPartGeometry = [&pointsToRender, &linesToRender, &polygonsToRender, &getPartGeometry, &context, &clippingEnabled, &markers, &feature, &usingSegmentizedGeometry, this]( const QgsAbstractGeometry * part, int partIndex = 0 )
1361  {
1362  Q_UNUSED( feature )
1363 
1364  if ( !part )
1365  return;
1366 
1367  // geometry preprocessing
1368  QgsGeometry temporaryGeometryContainer;
1369  const QgsAbstractGeometry *processedGeometry = nullptr;
1370 
1371  const bool isMultiPart = qgsgeometry_cast< const QgsGeometryCollection * >( part ) && qgsgeometry_cast< const QgsGeometryCollection * >( part )->numGeometries() > 1;
1372 
1373  if ( !isMultiPart )
1374  {
1375  // segmentize curved geometries
1376  const bool needsSegmentizing = QgsWkbTypes::isCurvedType( part->wkbType() ) || part->hasCurvedSegments();
1377  if ( needsSegmentizing )
1378  {
1379  std::unique_ptr< QgsAbstractGeometry > segmentizedPart( part->segmentize( context.segmentationTolerance(), context.segmentationToleranceType() ) );
1380  if ( !segmentizedPart )
1381  {
1382  return;
1383  }
1384  temporaryGeometryContainer.set( segmentizedPart.release() );
1385  processedGeometry = temporaryGeometryContainer.constGet();
1386  usingSegmentizedGeometry = true;
1387  }
1388  else
1389  {
1390  // no segmentation required
1391  processedGeometry = part;
1392  }
1393 
1394  // Simplify the geometry, if needed.
1395  if ( context.vectorSimplifyMethod().forceLocalOptimization() )
1396  {
1397  const int simplifyHints = context.vectorSimplifyMethod().simplifyHints();
1398  const QgsMapToPixelSimplifier simplifier( simplifyHints, context.vectorSimplifyMethod().tolerance(),
1399  static_cast< QgsMapToPixelSimplifier::SimplifyAlgorithm >( context.vectorSimplifyMethod().simplifyAlgorithm() ) );
1400 
1401  std::unique_ptr< QgsAbstractGeometry > simplified( simplifier.simplify( processedGeometry ) );
1402  if ( simplified )
1403  {
1404  temporaryGeometryContainer.set( simplified.release() );
1405  processedGeometry = temporaryGeometryContainer.constGet();
1406  }
1407  }
1408 
1409  // clip geometry to render context clipping regions
1410  if ( !context.featureClipGeometry().isEmpty() )
1411  {
1412  // apply feature clipping from context to the rendered geometry only -- just like the render time simplification,
1413  // we should NEVER apply this to the geometry attached to the feature itself. Doing so causes issues with certain
1414  // renderer settings, e.g. if polygons are being rendered using a rule based renderer based on the feature's area,
1415  // then we need to ensure that the original feature area is used instead of the clipped area..
1416  QgsGeos geos( processedGeometry );
1417  std::unique_ptr< QgsAbstractGeometry > clippedGeom( geos.intersection( context.featureClipGeometry().constGet() ) );
1418  if ( clippedGeom )
1419  {
1420  temporaryGeometryContainer.set( clippedGeom.release() );
1421  processedGeometry = temporaryGeometryContainer.constGet();
1422  }
1423  }
1424  }
1425  else
1426  {
1427  // for multipart geometries, the processing is deferred till we're rendering the actual part...
1428  processedGeometry = part;
1429  }
1430 
1431  if ( !processedGeometry )
1432  {
1433  // shouldn't happen!
1434  QgsDebugMsg( QStringLiteral( "No processed geometry to render for part!" ) );
1435  return;
1436  }
1437 
1438  switch ( QgsWkbTypes::flatType( processedGeometry->wkbType() ) )
1439  {
1440  case QgsWkbTypes::Point:
1441  {
1443  {
1444  QgsDebugMsgLevel( QStringLiteral( "point can be drawn only with marker symbol!" ), 2 );
1445  break;
1446  }
1447 
1448  PointInfo info;
1449  info.originalGeometry = qgsgeometry_cast< const QgsPoint * >( part );
1450  info.renderPoint = _getPoint( context, *info.originalGeometry );
1451  pointsToRender << info;
1452  break;
1453  }
1454 
1456  {
1457  if ( mType != Qgis::SymbolType::Line )
1458  {
1459  QgsDebugMsgLevel( QStringLiteral( "linestring can be drawn only with line symbol!" ), 2 );
1460  break;
1461  }
1462 
1463  LineInfo info;
1464  info.originalGeometry = qgsgeometry_cast<const QgsCurve *>( part );
1465  info.renderLine = _getLineString( context, *qgsgeometry_cast<const QgsCurve *>( processedGeometry ), clippingEnabled );
1466  linesToRender << info;
1467  break;
1468  }
1469 
1470  case QgsWkbTypes::Polygon:
1471  case QgsWkbTypes::Triangle:
1472  {
1473  QPolygonF pts;
1474  if ( mType != Qgis::SymbolType::Fill )
1475  {
1476  QgsDebugMsgLevel( QStringLiteral( "polygon can be drawn only with fill symbol!" ), 2 );
1477  break;
1478  }
1479 
1480  PolygonInfo info;
1481  info.originalGeometry = qgsgeometry_cast<const QgsCurvePolygon *>( part );
1482  info.originalPartIndex = partIndex;
1483  if ( !qgsgeometry_cast<const QgsPolygon *>( processedGeometry )->exteriorRing() )
1484  {
1485  QgsDebugMsg( QStringLiteral( "cannot render polygon with no exterior ring" ) );
1486  break;
1487  }
1488 
1489  _getPolygon( info.renderExterior, info.renderRings, context, *qgsgeometry_cast<const QgsPolygon *>( processedGeometry ), clippingEnabled, mForceRHR );
1490  polygonsToRender << info;
1491  break;
1492  }
1493 
1495  {
1496  const QgsMultiPoint *mp = qgsgeometry_cast< const QgsMultiPoint * >( processedGeometry );
1497  markers.reserve( mp->numGeometries() );
1498  }
1499  FALLTHROUGH
1503  {
1504  const QgsGeometryCollection *geomCollection = qgsgeometry_cast<const QgsGeometryCollection *>( processedGeometry );
1505 
1506  const unsigned int num = geomCollection->numGeometries();
1507  for ( unsigned int i = 0; i < num; ++i )
1508  {
1509  if ( context.renderingStopped() )
1510  break;
1511 
1512  getPartGeometry( geomCollection->geometryN( i ), i );
1513  }
1514  break;
1515  }
1516 
1519  {
1520  if ( mType != Qgis::SymbolType::Fill )
1521  {
1522  QgsDebugMsgLevel( QStringLiteral( "multi-polygon can be drawn only with fill symbol!" ), 2 );
1523  break;
1524  }
1525 
1526  QPolygonF pts;
1527 
1528  const QgsGeometryCollection *geomCollection = dynamic_cast<const QgsGeometryCollection *>( processedGeometry );
1529  const unsigned int num = geomCollection->numGeometries();
1530 
1531  // Sort components by approximate area (probably a bit faster than using
1532  // area() )
1533  std::map<double, QList<unsigned int> > thisAreaToPartNum;
1534  for ( unsigned int i = 0; i < num; ++i )
1535  {
1536  const QgsRectangle r( geomCollection->geometryN( i )->boundingBox() );
1537  thisAreaToPartNum[ r.width() * r.height()] << i;
1538  }
1539 
1540  // Draw starting with larger parts down to smaller parts, so that in
1541  // case of a part being incorrectly inside another part, it is drawn
1542  // on top of it (#15419)
1543  std::map<double, QList<unsigned int> >::const_reverse_iterator iter = thisAreaToPartNum.rbegin();
1544  for ( ; iter != thisAreaToPartNum.rend(); ++iter )
1545  {
1546  const QList<unsigned int> &listPartIndex = iter->second;
1547  for ( int idx = 0; idx < listPartIndex.size(); ++idx )
1548  {
1549  const unsigned i = listPartIndex[idx];
1550  getPartGeometry( geomCollection->geometryN( i ), i );
1551  }
1552  }
1553  break;
1554  }
1555 
1556  default:
1557  QgsDebugMsg( QStringLiteral( "feature %1: unsupported wkb type %2/%3 for rendering" )
1558  .arg( feature.id() )
1559  .arg( QgsWkbTypes::displayString( part->wkbType() ) )
1560  .arg( part->wkbType(), 0, 16 ) );
1561  }
1562  };
1563 
1564  // Use the simplified type ref when rendering -- this avoids some unnecessary cloning/geometry modification
1565  // (e.g. if the original geometry is a compound curve containing only a linestring curve, we don't have
1566  // to segmentize the geometry before rendering)
1567  getPartGeometry( geom.constGet()->simplifiedTypeRef(), 0 );
1568 
1569  // step 2 - determine which layers to render
1570  std::vector< int > layers;
1571  if ( layer == -1 )
1572  {
1573  layers.reserve( mLayers.count() );
1574  for ( int i = 0; i < mLayers.count(); ++i )
1575  layers.emplace_back( i );
1576  }
1577  else
1578  {
1579  layers.emplace_back( layer );
1580  }
1581 
1582  // step 3 - render these geometries using the desired symbol layers.
1583 
1584  if ( needsExpressionContext )
1585  mSymbolRenderContext->expressionContextScope()->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "symbol_layer_count" ), mLayers.count(), true ) );
1586 
1587  for ( const int symbolLayerIndex : layers )
1588  {
1589  QgsSymbolLayer *symbolLayer = mLayers.value( symbolLayerIndex );
1590  if ( !symbolLayer || !symbolLayer->enabled() )
1591  continue;
1592 
1593  if ( needsExpressionContext )
1594  mSymbolRenderContext->expressionContextScope()->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "symbol_layer_index" ), symbolLayerIndex + 1, true ) );
1595 
1596  symbolLayer->startFeatureRender( feature, context );
1597 
1598  switch ( mType )
1599  {
1601  {
1602  int geometryPartNumber = 0;
1603  for ( const PointInfo &point : std::as_const( pointsToRender ) )
1604  {
1605  if ( context.renderingStopped() )
1606  break;
1607 
1608  mSymbolRenderContext->setGeometryPartNum( geometryPartNumber + 1 );
1609  if ( needsExpressionContext )
1610  mSymbolRenderContext->expressionContextScope()->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_PART_NUM, geometryPartNumber + 1, true ) );
1611 
1612  static_cast<QgsMarkerSymbol *>( this )->renderPoint( point.renderPoint, &feature, context, symbolLayerIndex, selected );
1613  geometryPartNumber++;
1614  }
1615 
1616  break;
1617  }
1618 
1620  {
1621  if ( linesToRender.empty() )
1622  break;
1623 
1624  int geometryPartNumber = 0;
1625  for ( const LineInfo &line : std::as_const( linesToRender ) )
1626  {
1627  if ( context.renderingStopped() )
1628  break;
1629 
1630  mSymbolRenderContext->setGeometryPartNum( geometryPartNumber + 1 );
1631  if ( needsExpressionContext )
1632  mSymbolRenderContext->expressionContextScope()->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_PART_NUM, geometryPartNumber + 1, true ) );
1633 
1634  context.setGeometry( line.originalGeometry );
1635  static_cast<QgsLineSymbol *>( this )->renderPolyline( line.renderLine, &feature, context, symbolLayerIndex, selected );
1636  geometryPartNumber++;
1637  }
1638  break;
1639  }
1640 
1642  {
1643  for ( const PolygonInfo &info : std::as_const( polygonsToRender ) )
1644  {
1645  if ( context.renderingStopped() )
1646  break;
1647 
1648  mSymbolRenderContext->setGeometryPartNum( info.originalPartIndex + 1 );
1649  if ( needsExpressionContext )
1650  mSymbolRenderContext->expressionContextScope()->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_PART_NUM, info.originalPartIndex + 1, true ) );
1651 
1652  context.setGeometry( info.originalGeometry );
1653  static_cast<QgsFillSymbol *>( this )->renderPolygon( info.renderExterior, ( !info.renderRings.isEmpty() ? &info.renderRings : nullptr ), &feature, context, symbolLayerIndex, selected );
1654  }
1655 
1656  break;
1657  }
1658 
1660  break;
1661  }
1662 
1663  symbolLayer->stopFeatureRender( feature, context );
1664  }
1665 
1666  // step 4 - handle post processing steps
1667  switch ( mType )
1668  {
1670  {
1671  markers.reserve( pointsToRender.size() );
1672  for ( const PointInfo &info : std::as_const( pointsToRender ) )
1673  {
1674  if ( context.hasRenderedFeatureHandlers() || context.testFlag( Qgis::RenderContextFlag::DrawSymbolBounds ) )
1675  {
1676  const QRectF bounds = static_cast<QgsMarkerSymbol *>( this )->bounds( info.renderPoint, context, feature );
1677  if ( context.hasRenderedFeatureHandlers() )
1678  {
1679  renderedBoundsGeom = renderedBoundsGeom.isNull() ? QgsGeometry::fromRect( bounds )
1680  : QgsGeometry::collectGeometry( QVector< QgsGeometry>() << QgsGeometry::fromRect( QgsRectangle( bounds ) ) << renderedBoundsGeom );
1681  }
1682  if ( context.testFlag( Qgis::RenderContextFlag::DrawSymbolBounds ) )
1683  {
1684  //draw debugging rect
1685  context.painter()->setPen( Qt::red );
1686  context.painter()->setBrush( QColor( 255, 0, 0, 100 ) );
1687  context.painter()->drawRect( bounds );
1688  }
1689  }
1690 
1691  if ( drawVertexMarker && !usingSegmentizedGeometry )
1692  {
1693  markers.append( info.renderPoint );
1694  }
1695  }
1696  break;
1697  }
1698 
1700  {
1701  for ( const LineInfo &info : std::as_const( linesToRender ) )
1702  {
1703  if ( context.hasRenderedFeatureHandlers() && !info.renderLine.empty() )
1704  {
1705  renderedBoundsGeom = renderedBoundsGeom.isNull() ? QgsGeometry::fromQPolygonF( info.renderLine )
1706  : QgsGeometry::collectGeometry( QVector< QgsGeometry>() << QgsGeometry::fromQPolygonF( info.renderLine ) << renderedBoundsGeom );
1707  }
1708 
1709  if ( drawVertexMarker && !usingSegmentizedGeometry )
1710  {
1711  markers << info.renderLine;
1712  }
1713  }
1714  break;
1715  }
1716 
1718  {
1719  int i = 0;
1720  for ( const PolygonInfo &info : std::as_const( polygonsToRender ) )
1721  {
1722  if ( context.hasRenderedFeatureHandlers() && !info.renderExterior.empty() )
1723  {
1724  renderedBoundsGeom = renderedBoundsGeom.isNull() ? QgsGeometry::fromQPolygonF( info.renderExterior )
1725  : QgsGeometry::collectGeometry( QVector< QgsGeometry>() << QgsGeometry::fromQPolygonF( info.renderExterior ) << renderedBoundsGeom );
1726  // TODO: consider holes?
1727  }
1728 
1729  if ( drawVertexMarker && !usingSegmentizedGeometry )
1730  {
1731  markers << info.renderExterior;
1732 
1733  for ( const QPolygonF &hole : info.renderRings )
1734  {
1735  markers << hole;
1736  }
1737  }
1738  i++;
1739  }
1740  break;
1741  }
1742 
1744  break;
1745  }
1746 
1747  if ( context.hasRenderedFeatureHandlers() && !renderedBoundsGeom.isNull() )
1748  {
1750  const QList< QgsRenderedFeatureHandlerInterface * > handlers = context.renderedFeatureHandlers();
1751  for ( QgsRenderedFeatureHandlerInterface *handler : handlers )
1752  handler->handleRenderedFeature( feature, renderedBoundsGeom, featureContext );
1753  }
1754 
1755  if ( drawVertexMarker )
1756  {
1757  if ( !markers.isEmpty() && !context.renderingStopped() )
1758  {
1759  const auto constMarkers = markers;
1760  for ( QPointF marker : constMarkers )
1761  {
1762  renderVertexMarker( marker, context, currentVertexMarkerType, currentVertexMarkerSize );
1763  }
1764  }
1765  else
1766  {
1767  QgsCoordinateTransform ct = context.coordinateTransform();
1768  const QgsMapToPixel &mtp = context.mapToPixel();
1769 
1770  QgsPoint vertexPoint;
1771  QgsVertexId vertexId;
1772  double x, y, z;
1773  QPointF mapPoint;
1774  while ( geom.constGet()->nextVertex( vertexId, vertexPoint ) )
1775  {
1776  //transform
1777  x = vertexPoint.x();
1778  y = vertexPoint.y();
1779  z = 0.0;
1780  if ( ct.isValid() )
1781  {
1782  ct.transformInPlace( x, y, z );
1783  }
1784  mapPoint.setX( x );
1785  mapPoint.setY( y );
1786  mtp.transformInPlace( mapPoint.rx(), mapPoint.ry() );
1787  renderVertexMarker( mapPoint, context, currentVertexMarkerType, currentVertexMarkerSize );
1788  }
1789  }
1790  }
1791 }
1792 
1794 {
1795  return mSymbolRenderContext.get();
1796 }
1797 
1798 void QgsSymbol::renderVertexMarker( QPointF pt, QgsRenderContext &context, Qgis::VertexMarkerType currentVertexMarkerType, double currentVertexMarkerSize )
1799 {
1800  int markerSize = context.convertToPainterUnits( currentVertexMarkerSize, QgsUnitTypes::RenderMillimeters );
1801  QgsSymbolLayerUtils::drawVertexMarker( pt.x(), pt.y(), *context.painter(), currentVertexMarkerType, markerSize );
1802 }
1803 
1804 void QgsSymbol::initPropertyDefinitions()
1805 {
1806  if ( !sPropertyDefinitions.isEmpty() )
1807  return;
1808 
1809  QString origin = QStringLiteral( "symbol" );
1810 
1811  sPropertyDefinitions = QgsPropertiesDefinition
1812  {
1813  { QgsSymbol::PropertyOpacity, QgsPropertyDefinition( "alpha", QObject::tr( "Opacity" ), QgsPropertyDefinition::Opacity, origin )},
1814  };
1815 }
1816 
1817 void QgsSymbol::startFeatureRender( const QgsFeature &feature, QgsRenderContext &context, const int layer )
1818 {
1819  if ( layer != -1 )
1820  {
1822  if ( symbolLayer && symbolLayer->enabled() )
1823  {
1824  symbolLayer->startFeatureRender( feature, context );
1825  }
1826  return;
1827  }
1828  else
1829  {
1830  const QList< QgsSymbolLayer * > layers = mLayers;
1831  for ( QgsSymbolLayer *symbolLayer : layers )
1832  {
1833  if ( !symbolLayer->enabled() )
1834  continue;
1835 
1836  symbolLayer->startFeatureRender( feature, context );
1837  }
1838  }
1839 }
1840 
1841 void QgsSymbol::stopFeatureRender( const QgsFeature &feature, QgsRenderContext &context, int layer )
1842 {
1843  if ( layer != -1 )
1844  {
1846  if ( symbolLayer && symbolLayer->enabled() )
1847  {
1848  symbolLayer->stopFeatureRender( feature, context );
1849  }
1850  return;
1851  }
1852  else
1853  {
1854  const QList< QgsSymbolLayer * > layers = mLayers;
1855  for ( QgsSymbolLayer *symbolLayer : layers )
1856  {
1857  if ( !symbolLayer->enabled() )
1858  continue;
1859 
1860  symbolLayer->stopFeatureRender( feature, context );
1861  }
1862  }
1863 }
QgsCurve
Abstract base class for curved geometry type.
Definition: qgscurve.h:35
qgspolygon.h
QgsLineSymbolLayer
Definition: qgssymbollayer.h:1024
QgsSymbol::setLayer
Q_DECL_DEPRECATED void setLayer(const QgsVectorLayer *layer)
Definition: qgssymbol.cpp:1196
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:406
QgsSymbol::cloneLayers
QgsSymbolLayerList cloneLayers() const
Retrieve a cloned list of all layers that make up this symbol.
Definition: qgssymbol.cpp:1116
QgsSymbol::_getPolygonRing
static QPolygonF _getPolygonRing(QgsRenderContext &context, const QgsCurve &curve, bool clipToExtent, bool isExteriorRing=false, bool correctRingOrientation=false)
Creates a polygon ring in screen coordinates from a QgsCurve in map coordinates.
Definition: qgssymbol.cpp:287
QgsSymbolLayer::enabled
bool enabled() const
Returns true if symbol layer is enabled and will be drawn.
Definition: qgssymbollayer.h:242
QgsCoordinateTransform::transformCoords
void transformCoords(int numPoint, double *x, double *y, double *z, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward) const SIP_THROW(QgsCsException)
Transform an array of coordinates to the destination CRS.
Definition: qgscoordinatetransform.cpp:705
QgsSymbol::mLayer
const Q_DECL_DEPRECATED QgsVectorLayer * mLayer
Definition: qgssymbol.h:805
qgsexpressioncontextutils.h
QgsExpressionContext::appendScopes
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
Definition: qgsexpressioncontext.cpp:499
QgsSymbol::color
QColor color() const
Returns the symbol's color.
Definition: qgssymbol.cpp:877
QgsSymbol::renderVertexMarker
void renderVertexMarker(QPointF pt, QgsRenderContext &context, Qgis::VertexMarkerType currentVertexMarkerType, double currentVertexMarkerSize)
Render editing vertex marker at specified point.
Definition: qgssymbol.cpp:1798
QgsPropertyCollection::prepare
bool prepare(const QgsExpressionContext &context=QgsExpressionContext()) const override
Prepares the collection against a specified expression context.
Definition: qgspropertycollection.cpp:240
QgsRectangle::height
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
Definition: qgsrectangle.h:230
QgsCoordinateTransform::transformInPlace
void transformInPlace(double &x, double &y, double &z, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward) const SIP_THROW(QgsCsException)
Transforms an array of x, y and z double coordinates in place, from the source CRS to the destination...
Definition: qgscoordinatetransform.cpp:364
Qgis::RenderContextFlag::RenderSymbolPreview
@ RenderSymbolPreview
The render is for a symbol preview only and map based properties may not be available,...
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
QgsSymbol::symbolTypeToString
static QString symbolTypeToString(Qgis::SymbolType type)
Returns a translated string version of the specified symbol type.
Definition: qgssymbol.cpp:533
QgsSymbolLayerUtils::encodeColor
static QString encodeColor(const QColor &color)
Definition: qgssymbollayerutils.cpp:64
QgsClipper::clippedLine
static QPolygonF clippedLine(const QgsCurve &curve, const QgsRectangle &clipExtent)
Takes a linestring and clips it to clipExtent.
Definition: qgsclipper.cpp:110
QgsRenderContext::setIsGuiPreview
void setIsGuiPreview(bool preview)
Sets GUI preview mode.
Definition: qgsrendercontext.h:800
QgsRenderContext::setPainterFlagsUsingContext
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
Definition: qgsrendercontext.cpp:169
Qgis::RenderContextFlag::HighQualityImageTransforms
@ HighQualityImageTransforms
Enable high quality image transformations, which results in better appearance of scaled or rotated ra...
QgsSymbolLayer::startFeatureRender
virtual void startFeatureRender(const QgsFeature &feature, QgsRenderContext &context)
Called before the layer will be rendered for a particular feature.
Definition: qgssymbollayer.cpp:131
QgsRenderContext::mapToPixel
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
Definition: qgsrendercontext.h:258
QgsWkbTypes::Triangle
@ Triangle
Definition: qgswkbtypes.h:75
QgsWkbTypes::displayString
static QString displayString(Type type) SIP_HOLDGIL
Returns a non-translated display string type for a WKB type, e.g., the geometry name used in WKT geom...
Definition: qgswkbtypes.cpp:145
QgsSymbolLayerUtils::drawVertexMarker
static void drawVertexMarker(double x, double y, QPainter &p, Qgis::VertexMarkerType type, int markerSize)
Draws a vertex symbol at (painter) coordinates x, y.
Definition: qgssymbollayerutils.cpp:1090
QgsProperty
A store for object properties.
Definition: qgsproperty.h:230
QgsUnitTypes::RenderUnit
RenderUnit
Rendering size units.
Definition: qgsunittypes.h:167
QgsWkbTypes::Point
@ Point
Definition: qgswkbtypes.h:72
qgsprojectstylesettings.h
Qgis::SymbolType::Fill
@ Fill
Fill symbol.
Qgis::SymbolType::Line
@ Line
Line symbol.
QgsRenderContext::expressionContext
QgsExpressionContext & expressionContext()
Gets the expression context.
Definition: qgsrendercontext.h:625
Qgis::SymbolPreviewFlag::FlagIncludeCrosshairsForMarkerSymbols
@ FlagIncludeCrosshairsForMarkerSymbols
Include a crosshairs reference image in the background of marker symbol previews.
QgsPolygon
Polygon geometry type.
Definition: qgspolygon.h:33
qgslinestring.h
QgsSymbol::defaultSymbol
static QgsSymbol * defaultSymbol(QgsWkbTypes::GeometryType geomType)
Returns a new default symbol for the specified geometry type.
Definition: qgssymbol.cpp:673
QgsEffectPainter
A class to manager painter saving and restoring required for effect drawing.
Definition: qgspainteffect.h:395
QgsWkbTypes::MultiPolygon
@ MultiPolygon
Definition: qgswkbtypes.h:78
QgsWkbTypes::NullGeometry
@ NullGeometry
Definition: qgswkbtypes.h:146
QgsPoint
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:48
QgsClipper::clipped3dLine
static void clipped3dLine(const QVector< double > &xIn, const QVector< double > &yIn, const QVector< double > &zIn, QVector< double > &x, QVector< double > &y, QVector< double > &z, const QgsBox3d &clipExtent)
Takes a line with 3D coordinates and clips it to clipExtent.
Definition: qgsclipper.cpp:40
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QgsSymbol::QgsSymbol
QgsSymbol(Qgis::SymbolType type, const QgsSymbolLayerList &layers)
Constructor for a QgsSymbol of the specified type.
Definition: qgssymbol.cpp:63
QgsCurvePolygon::exteriorRing
const QgsCurve * exteriorRing() const SIP_HOLDGIL
Returns the curve polygon's exterior ring.
Definition: qgscurvepolygon.h:96
QgsSymbol::takeSymbolLayer
QgsSymbolLayer * takeSymbolLayer(int index)
Removes a symbol layer from the list and returns a pointer to it.
Definition: qgssymbol.cpp:769
Qgis::RenderContextFlag::RenderMapTile
@ RenderMapTile
Draw map such that there are no problems between adjacent tiles.
QgsWkbTypes::flatType
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:732
QgsCurvePolygon
Curve polygon geometry type.
Definition: qgscurvepolygon.h:34
QgsSymbol::layer
const Q_DECL_DEPRECATED QgsVectorLayer * layer() const
Definition: qgssymbol.cpp:1203
QgsWkbTypes::LineString
@ LineString
Definition: qgswkbtypes.h:73
QgsFields
Container of fields for a vector layer.
Definition: qgsfields.h:44
QgsRectangle::yMinimum
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
QgsSymbolRenderContext::setSelected
void setSelected(bool selected)
Sets whether symbols should be rendered using the selected symbol coloring and style.
Definition: qgssymbolrendercontext.h:124
geos
Contains geos related utilities and functions.
Definition: qgsgeos.h:41
qgsfeature.h
qgsmultipoint.h
QgsRenderContext::testFlag
bool testFlag(Qgis::RenderContextFlag flag) const
Check whether a particular flag is enabled.
Definition: qgsrendercontext.cpp:229
QgsRenderContext::flags
Qgis::RenderContextFlags flags() const
Returns combination of flags used for rendering.
Definition: qgsrendercontext.cpp:224
qgsmarkersymbollayer.h
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:71
Qgis::RenderContextFlag::DrawSymbolBounds
@ DrawSymbolBounds
Draw bounds of symbols (for debugging/testing)
qgsrenderedfeaturehandlerinterface.h
QgsRenderContext
Contains information about the context of a rendering operation.
Definition: qgsrendercontext.h:59
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:480
QgsSymbol::hasDataDefinedProperties
bool hasDataDefinedProperties() const
Returns whether the symbol utilizes any data defined properties.
Definition: qgssymbol.cpp:1173
QgsApplication::colorSchemeRegistry
static QgsColorSchemeRegistry * colorSchemeRegistry()
Returns the application's color scheme registry, used for managing color schemes.
Definition: qgsapplication.cpp:2310
QgsUnitTypes::RenderMillimeters
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:169
QgsExpressionContextUtils::globalProjectLayerScopes
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Definition: qgsexpressioncontextutils.cpp:377
QgsSymbolAnimationSettings::frameRate
double frameRate() const
Returns the symbol animation frame rate (in frames per second).
Definition: qgssymbol.h:77
QgsSymbol::symbolTypeForGeometryType
static Qgis::SymbolType symbolTypeForGeometryType(QgsWkbTypes::GeometryType type)
Returns the default symbol type required for the specified geometry type.
Definition: qgssymbol.cpp:549
QgsWkbTypes::MultiCurve
@ MultiCurve
Definition: qgswkbtypes.h:83
QgsSymbol::mapUnitScale
QgsMapUnitScale mapUnitScale() const
Returns the map unit scale for the symbol.
Definition: qgssymbol.cpp:616
QgsExpressionContext::EXPR_GEOMETRY_PART_NUM
static const QString EXPR_GEOMETRY_PART_NUM
Inbuilt variable name for geometry part number variable.
Definition: qgsexpressioncontext.h:813
QgsRenderContext::currentFrame
long long currentFrame() const
Returns the current frame number of the map (in frames per second), for maps which are part of an ani...
Definition: qgsrendercontext.cpp:695
FALLTHROUGH
#define FALLTHROUGH
Definition: qgis.h:2847
QgsSymbol
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:92
QgsAbstractGeometry::partCount
virtual int partCount() const =0
Returns count of parts contained in the geometry.
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
qgspainteffect.h
QgsLineString
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:44
QgsSymbol::dataDefinedProperties
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol's property collection, used for data defined overrides.
Definition: qgssymbol.h:622
QgsSymbol::symbolLayer
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
Definition: qgssymbol.cpp:725
QgsSymbol::insertSymbolLayer
bool insertSymbolLayer(int index, QgsSymbolLayer *layer)
Inserts a symbol layer to specified index.
Definition: qgssymbol.cpp:735
QgsCoordinateTransform::isValid
bool isValid() const
Returns true if the coordinate transform is valid, ie both the source and destination CRS have been s...
Definition: qgscoordinatetransform.cpp:900
QgsRenderContext::extent
const QgsRectangle & extent() const
When rendering a map layer, calling this method returns the "clipping" extent for the layer (in the l...
Definition: qgsrendercontext.h:239
QgsSymbol::outputUnit
QgsUnitTypes::RenderUnit outputUnit() const
Returns the units to use for sizes and widths within the symbol.
Definition: qgssymbol.cpp:578
QgsRenderContext::frameRate
double frameRate() const
Returns the frame rate of the map, for maps which are part of an animation.
Definition: qgsrendercontext.cpp:685
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QgsSymbol::setOutputUnit
void setOutputUnit(QgsUnitTypes::RenderUnit unit) const
Sets the units to use for sizes and widths within the symbol.
Definition: qgssymbol.cpp:640
QgsWkbTypes::PolygonGeometry
@ PolygonGeometry
Definition: qgswkbtypes.h:144
QgsStyle::defaultPatchAsQPolygonF
QList< QList< QPolygonF > > defaultPatchAsQPolygonF(Qgis::SymbolType type, QSizeF size) const
Returns the default patch geometry for the given symbol type and size as a set of QPolygonF objects (...
Definition: qgsstyle.cpp:1199
QgsLegendPatchShape
Represents a patch shape for use in map legends.
Definition: qgslegendpatchshape.h:33
qgsDoubleToString
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:2204
QgsSymbol::PropertyOpacity
@ PropertyOpacity
Opacity.
Definition: qgssymbol.h:131
QgsGeometryCollection::numGeometries
int numGeometries() const SIP_HOLDGIL
Returns the number of geometries within the collection.
Definition: qgsgeometrycollection.h:58
QgsRenderedFeatureHandlerInterface
An interface for classes which provider custom handlers for features rendered as part of a map render...
Definition: qgsrenderedfeaturehandlerinterface.h:46
QgsRenderContext::isSymbolLayerEnabled
bool isSymbolLayerEnabled(const QgsSymbolLayer *layer) const
When rendering a map layer in a second pass (for selective masking), some symbol layers may be disabl...
Definition: qgsrendercontext.h:166
QgsSymbol::exportImage
void exportImage(const QString &path, const QString &format, QSize size)
Export the symbol as an image format, to the specified path and with the given size.
Definition: qgssymbol.cpp:989
QgsSymbolRenderContext::setPatchShape
void setPatchShape(const QgsLegendPatchShape &shape)
Sets the symbol patch shape, to use if rendering symbol preview icons.
Definition: qgssymbolrendercontext.cpp:77
QgsLineString::xVector
QVector< double > xVector() const
Returns the x vertex values as a vector.
Definition: qgslinestring.h:466
QgsStyle::defaultStyle
static QgsStyle * defaultStyle()
Returns default application-wide style.
Definition: qgsstyle.cpp:145
qgsapplication.h
QgsSymbolRenderContext
Definition: qgssymbolrendercontext.h:35
QgsCurvePolygon::numInteriorRings
int numInteriorRings() const SIP_HOLDGIL
Returns the number of interior rings contained with the curve polygon.
Definition: qgscurvepolygon.h:86
Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:2820
QgsRenderContext::renderingStopped
bool renderingStopped() const
Returns true if the rendering operation has been stopped and any ongoing rendering should be canceled...
Definition: qgsrendercontext.h:285
QgsRectangle::xMaximum
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
QgsRenderContext::coordinateTransform
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
Definition: qgsrendercontext.h:178
QgsPoint::y
double y
Definition: qgspoint.h:70
QgsSymbol::opacity
qreal opacity() const
Returns the opacity for the symbol.
Definition: qgssymbol.h:495
QgsSymbol::setMapUnitScale
void setMapUnitScale(const QgsMapUnitScale &scale) const
Sets the map unit scale for the symbol.
Definition: qgssymbol.cpp:649
QgsLineString::zVector
QVector< double > zVector() const
Returns the z vertex values as a vector.
Definition: qgslinestring.h:486
QgsWkbTypes::MultiLineString
@ MultiLineString
Definition: qgswkbtypes.h:77
QgsMapLayer::flags
QgsMapLayer::LayerFlags flags() const
Returns the flags for this layer.
Definition: qgsmaplayer.cpp:150
QgsGeometryCollection
Geometry collection.
Definition: qgsgeometrycollection.h:36
QgsPropertiesDefinition
QMap< int, QgsPropertyDefinition > QgsPropertiesDefinition
Definition of available properties.
Definition: qgspropertycollection.h:29
QgsCurve::orientation
Qgis::AngularDirection orientation() const
Returns the curve's orientation, e.g.
Definition: qgscurve.cpp:286
QgsSymbol::propertyDefinitions
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol property definitions.
Definition: qgssymbol.cpp:566
QgsCsException
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:65
QgsSymbolLayer
Definition: qgssymbollayer.h:54
QgsRenderContext::forceVectorOutput
bool forceVectorOutput() const
Returns true if rendering operations should use vector operations instead of any faster raster shortc...
Definition: qgsrendercontext.cpp:295
QgsSymbol::setAnimationSettings
void setAnimationSettings(const QgsSymbolAnimationSettings &settings)
Sets a the symbol animation settings.
Definition: qgssymbol.cpp:668
QgsSymbol::flags
Qgis::SymbolFlags flags() const
Returns flags for the symbol.
Definition: qgssymbol.h:530
QgsSymbol::changeSymbolLayer
bool changeSymbolLayer(int index, QgsSymbolLayer *layer)
Deletes the current layer at the specified index and replaces it with layer.
Definition: qgssymbol.cpp:778
QgsSymbol::setDataDefinedProperty
void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the symbol.
Definition: qgssymbol.cpp:1168
QgsAbstractGeometry::wkbType
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
Definition: qgsabstractgeometry.h:206
QgsSymbol::appendSymbolLayer
bool appendSymbolLayer(QgsSymbolLayer *layer)
Appends a symbol layer at the end of the current symbol layer list.
Definition: qgssymbol.cpp:748
QgsSymbol::stopRender
void stopRender(QgsRenderContext &context)
Ends the rendering process.
Definition: qgssymbol.cpp:842
Qgis::SymbolType
SymbolType
Symbol types.
Definition: qgis.h:205
QgsSymbol::toSld
void toSld(QDomDocument &doc, QDomElement &element, QVariantMap props) const
Converts the symbol to a SLD representation.
Definition: qgssymbol.cpp:1103
QgsClipper::trimPolygon
static void trimPolygon(QPolygonF &pts, const QgsRectangle &clipRect)
Trims the given polygon to a rectangular box, by modifying the given polygon in place.
Definition: qgsclipper.h:285
QgsSymbol::mRenderHints
Qgis::SymbolRenderHints mRenderHints
Definition: qgssymbol.h:791
QgsMapToPixelSimplifier::SimplifyAlgorithm
SimplifyAlgorithm
Types of simplification algorithms that can be used.
Definition: qgsmaptopixelgeometrysimplifier.h:42
QgsSymbol::mLayers
QgsSymbolLayerList mLayers
Definition: qgssymbol.h:786
QgsSymbol::type
Qgis::SymbolType type() const
Returns the symbol's type.
Definition: qgssymbol.h:152
QgsSymbol::_getPolygon
static void _getPolygon(QPolygonF &pts, QVector< QPolygonF > &holes, QgsRenderContext &context, const QgsPolygon &polygon, bool clipToExtent=true, bool correctRingOrientation=false)
Creates a polygon in screen coordinates from a QgsPolygonXYin map coordinates.
Definition: qgssymbol.cpp:518
Qgis::VertexMarkerType
VertexMarkerType
Editing vertex markers, used for showing vertices during a edit operation.
Definition: qgis.h:806
QgsPropertyCollection::hasActiveProperties
bool hasActiveProperties() const override
Returns true if the collection has any active properties, or false if all properties within the colle...
Definition: qgspropertycollection.cpp:304
QgsCurve::asQPolygonF
virtual QPolygonF asQPolygonF() const
Returns a QPolygonF representing the points.
Definition: qgscurve.cpp:266
QgsMarkerSymbol
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgsmarkersymbol.h:30
QgsSymbolLayer::stopFeatureRender
virtual void stopFeatureRender(const QgsFeature &feature, QgsRenderContext &context)
Called after the layer has been rendered for a particular feature.
Definition: qgssymbollayer.cpp:143
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:2265
QgsRenderContext::setFlag
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
Definition: qgsrendercontext.cpp:216
QgsWkbTypes::GeometryCollection
@ GeometryCollection
Definition: qgswkbtypes.h:79
QgsAbstractGeometry::simplifiedTypeRef
virtual const QgsAbstractGeometry * simplifiedTypeRef() const SIP_HOLDGIL
Returns a reference to the simplest lossless representation of this geometry, e.g.
Definition: qgsabstractgeometry.cpp:287
QgsSymbol::dump
QString dump() const
Returns a string dump of the symbol's properties.
Definition: qgssymbol.cpp:1077
QgsRectangle::contains
bool contains(const QgsRectangle &rect) const SIP_HOLDGIL
Returns true when rectangle contains other rectangle.
Definition: qgsrectangle.h:363
QgsGeos
Does vector analysis using the geos library and handles import, export, exception handling*.
Definition: qgsgeos.h:103
QgsLineSymbolLayer::renderPolygonStroke
virtual void renderPolygonStroke(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context)
Renders the line symbol layer along the outline of polygon, using the given render context.
Definition: qgssymbollayer.cpp:762
QgsGeometryGeneratorSymbolLayer
Definition: qgsgeometrygeneratorsymbollayer.h:31
Qgis::RenderContextFlag::ApplyClipAfterReprojection
@ ApplyClipAfterReprojection
Feature geometry clipping to mapExtent() must be performed after the geometries are transformed using...
QgsSymbolAnimationSettings::isAnimated
bool isAnimated() const
Returns true if the symbol is animated.
Definition: qgssymbol.h:63
qgsrendercontext.h
QgsSymbol::startFeatureRender
void startFeatureRender(const QgsFeature &feature, QgsRenderContext &context, int layer=-1)
Called before symbol layers will be rendered for a particular feature.
Definition: qgssymbol.cpp:1817
QgsLineSymbol
A line symbol type, for rendering LineString and MultiLineString geometries.
Definition: qgslinesymbol.h:29
QgsPropertyDefinition
Definition for a property.
Definition: qgsproperty.h:46
Qgis::AngularDirection::CounterClockwise
@ CounterClockwise
Counter-clockwise direction.
QgsSymbol::renderFeature
void renderFeature(const QgsFeature &feature, QgsRenderContext &context, int layer=-1, bool selected=false, bool drawVertexMarker=false, Qgis::VertexMarkerType currentVertexMarkerType=Qgis::VertexMarkerType::SemiTransparentCircle, double currentVertexMarkerSize=0.0) SIP_THROW(QgsCsException)
Render a feature.
Definition: qgssymbol.cpp:1252
qgssymbollayer.h
QgsLineString::yVector
QVector< double > yVector() const
Returns the y vertex values as a vector.
Definition: qgslinestring.h:476
QgsSymbol::renderUsingLayer
void renderUsingLayer(QgsSymbolLayer *layer, QgsSymbolRenderContext &context, QgsWkbTypes::GeometryType geometryType=QgsWkbTypes::GeometryType::UnknownGeometry, const QPolygonF *points=nullptr, const QVector< QPolygonF > *rings=nullptr)
Renders a context using a particular symbol layer without passing in a geometry.
Definition: qgssymbol.cpp:1130
QgsGeometry::isNull
bool isNull
Definition: qgsgeometry.h:127
qgslegendpatchshape.h
QgsMapUnitScale
Struct for storing maximum and minimum scales for measurements in map units.
Definition: qgsmapunitscale.h:36
QgsSymbol::startRender
void startRender(QgsRenderContext &context, const QgsFields &fields=QgsFields())
Begins the rendering process for the symbol.
Definition: qgssymbol.cpp:794
QgsSymbolLayer::paintEffect
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the layer.
Definition: qgssymbollayer.cpp:223
QgsRectangle::xMinimum
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
QgsCurvePolygon::interiorRing
const QgsCurve * interiorRing(int i) const SIP_HOLDGIL
Retrieves an interior ring from the curve polygon.
Definition: qgscurvepolygon.h:122
qgseffectstack.h
qgsfillsymbollayer.h
QgsPropertyCollection::referencedFields
QSet< QString > referencedFields(const QgsExpressionContext &context=QgsExpressionContext(), bool ignoreContext=false) const override
Returns the set of any fields referenced by the active properties from the collection.
Definition: qgspropertycollection.cpp:254
QgsSymbol::symbolRenderContext
QgsSymbolRenderContext * symbolRenderContext()
Returns the symbol render context.
Definition: qgssymbol.cpp:1793
QgsGeometry::constGet
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Definition: qgsgeometry.cpp:136
QgsMultiPoint
Multi point geometry collection.
Definition: qgsmultipoint.h:29
QgsGeometryGeneratorSymbolLayer::render
void render(QgsSymbolRenderContext &context, QgsWkbTypes::GeometryType geometryType=QgsWkbTypes::GeometryType::UnknownGeometry, const QPolygonF *points=nullptr, const QVector< QPolygonF > *rings=nullptr)
Will render this symbol layer using the context.
Definition: qgsgeometrygeneratorsymbollayer.cpp:374
QgsAbstractGeometry
Abstract base class for all geometries.
Definition: qgsabstractgeometry.h:79
QgsExpressionContextScope
Single scope for storing variables and functions for use within a QgsExpressionContext....
Definition: qgsexpressioncontext.h:113
qgsclipper.h
qgsstyle.h
QgsSymbol::~QgsSymbol
virtual ~QgsSymbol()
Definition: qgssymbol.cpp:572
QgsAbstractGeometry::is3D
bool is3D() const SIP_HOLDGIL
Returns true if the geometry is 3D and contains a z-value.
Definition: qgsabstractgeometry.h:219
QgsMapToPixelSimplifier
Implementation of GeometrySimplifier using the "MapToPixel" algorithm.
Definition: qgsmaptopixelgeometrysimplifier.h:38
QgsSymbolLayer::PropertyLayerEnabled
@ PropertyLayerEnabled
Whether symbol layer is enabled.
Definition: qgssymbollayer.h:188
QgsExpressionContext::appendScope
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
Definition: qgsexpressioncontext.cpp:494
qgsvectorlayer.h
QgsRenderContext::convertToPainterUnits
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
Definition: qgsrendercontext.cpp:367
Qgis::SymbolLayerFlag::DisableFeatureClipping
@ DisableFeatureClipping
If present, indicates that features should never be clipped to the map extent during rendering.
QgsRenderContext::setForceVectorOutput
void setForceVectorOutput(bool force)
Sets whether rendering operations should use vector operations instead of any faster raster shortcuts...
Definition: qgsrendercontext.cpp:330
QgsExpressionContext::EXPR_GEOMETRY_PART_COUNT
static const QString EXPR_GEOMETRY_PART_COUNT
Inbuilt variable name for geometry part count variable.
Definition: qgsexpressioncontext.h:811
Qgis::AngularDirection::Clockwise
@ Clockwise
Clockwise direction.
QgsAbstractGeometry::boundingBox
virtual QgsRectangle boundingBox() const =0
Returns the minimal bounding box for the geometry.
QgsSymbol::mOpacity
qreal mOpacity
Symbol opacity (in the range 0 - 1)
Definition: qgssymbol.h:789
QgsRenderedFeatureHandlerInterface::RenderedFeatureContext
Definition: qgsrenderedfeaturehandlerinterface.h:51
QgsSymbolRenderContext::setOriginalGeometryType
void setOriginalGeometryType(QgsWkbTypes::GeometryType type)
Sets the geometry type for the original feature geometry being rendered.
Definition: qgssymbolrendercontext.h:150
Qgis::SymbolType::Hybrid
@ Hybrid
Hybrid symbol.
QgsMapToPixel::transformInPlace
void transformInPlace(double &x, double &y) const
Transforms device coordinates to map coordinates.
Definition: qgsmaptopixel.h:128
QgsWkbTypes::isCurvedType
static bool isCurvedType(Type type) SIP_HOLDGIL
Returns true if the WKB type is a curved type or can contain curved geometries.
Definition: qgswkbtypes.h:911
Qgis::RenderContextFlag::Antialiasing
@ Antialiasing
Use antialiasing while drawing.
QgsWkbTypes::LineGeometry
@ LineGeometry
Definition: qgswkbtypes.h:143
QgsWkbTypes::PointGeometry
@ PointGeometry
Definition: qgswkbtypes.h:142
QgsSymbol::_getPoint
static QPointF _getPoint(QgsRenderContext &context, const QgsPoint &point)
Creates a point in screen coordinates from a QgsPoint in map coordinates.
Definition: qgssymbol.h:718
QgsRenderContext::mapExtent
QgsRectangle mapExtent() const
Returns the original extent of the map being rendered.
Definition: qgsrendercontext.h:251
QgsRectangle::yMaximum
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
QgsGeometryCollection::geometryN
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
Definition: qgsgeometrycollection.h:86
qgsgeometry.h
QgsWkbTypes::MultiSurface
@ MultiSurface
Definition: qgswkbtypes.h:84
qgslinesymbollayer.h
QgsExpressionContextUtils::updateSymbolScope
static QgsExpressionContextScope * updateSymbolScope(const QgsSymbol *symbol, QgsExpressionContextScope *symbolScope=nullptr)
Updates a symbol scope related to a QgsSymbol to an expression context.
Definition: qgsexpressioncontextutils.cpp:538
QgsWkbTypes::GeometryType
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:140
QgsLegendPatchShape::toQPolygonF
QList< QList< QPolygonF > > toQPolygonF(Qgis::SymbolType type, QSizeF size) const
Converts the patch shape to a set of QPolygonF objects representing how the patch should be drawn for...
Definition: qgslegendpatchshape.cpp:143
QgsSymbol::clipFeaturesToExtent
bool clipFeaturesToExtent() const
Returns whether features drawn by the symbol will be clipped to the render context's extent.
Definition: qgssymbol.h:552
QgsSymbol::mType
Qgis::SymbolType mType
Definition: qgssymbol.h:785
QgsGeometry
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsMapToPixel
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:38
QgsSymbol::drawPreviewIcon
void drawPreviewIcon(QPainter *painter, QSize size, QgsRenderContext *customContext=nullptr, bool selected=false, const QgsExpressionContext *expressionContext=nullptr, const QgsLegendPatchShape *patchShape=nullptr)
Draws an icon of the symbol that occupies an area given by size using the specified painter.
Definition: qgssymbol.cpp:892
QgsSymbol::Property
Property
Data definable properties.
Definition: qgssymbol.h:129
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:391
QgsRectangle::width
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Definition: qgsrectangle.h:223
QgsSymbolLayerList
QList< QgsSymbolLayer * > QgsSymbolLayerList
Definition: qgssymbol.h:27
QgsRenderContext::fromQPainter
static QgsRenderContext fromQPainter(QPainter *painter)
Creates a default render context given a pixel based QPainter destination.
Definition: qgsrendercontext.cpp:143
qgsmarkersymbol.h
QgsWkbTypes::Polygon
@ Polygon
Definition: qgswkbtypes.h:74
QgsWkbTypes::MultiPoint
@ MultiPoint
Definition: qgswkbtypes.h:76
QgsMapToPixelSimplifier::simplify
QgsGeometry simplify(const QgsGeometry &geometry) const override
Returns a simplified version the specified geometry.
Definition: qgsmaptopixelgeometrysimplifier.cpp:382
QgsSymbol::usedAttributes
QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns a list of attributes required to render this feature.
Definition: qgssymbol.cpp:1151
QgsSymbol::deleteSymbolLayer
bool deleteSymbolLayer(int index)
Removes and deletes the symbol layer at the specified index.
Definition: qgssymbol.cpp:758
QgsGeometry::fromRect
static QgsGeometry fromRect(const QgsRectangle &rect) SIP_HOLDGIL
Creates a new geometry from a QgsRectangle.
Definition: qgsgeometry.cpp:241
QgsCurve::boundingBox
QgsRectangle boundingBox() const override
Returns the minimal bounding box for the geometry.
Definition: qgscurve.cpp:238
QgsVertexId
Utility class for identifying a unique vertex within a geometry.
Definition: qgsvertexid.h:30
qgsmaptopixelgeometrysimplifier.h
QgsPaintEffect
Base class for visual effects which can be applied to QPicture drawings.
Definition: qgspainteffect.h:52
QgsFillSymbol
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
Definition: qgsfillsymbol.h:29
qgscolorschemeregistry.h
qgsproperty.h
QgsUnitTypes::RenderUnknownUnit
@ RenderUnknownUnit
Mixed or unknown units.
Definition: qgsunittypes.h:175
QgsSymbolLayer::stopRender
virtual void stopRender(QgsSymbolRenderContext &context)=0
Called after a set of rendering operations has finished on the supplied render context.
QgsWkbTypes::UnknownGeometry
@ UnknownGeometry
Definition: qgswkbtypes.h:145
QgsSymbol::animationSettings
QgsSymbolAnimationSettings & animationSettings()
Returns a reference to the symbol animation settings.
Definition: qgssymbol.cpp:658
QgsSymbolAnimationSettings
Contains settings relating to symbol animation.
Definition: qgssymbol.h:39
QgsRenderContext::setExpressionContext
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
Definition: qgsrendercontext.h:617
QgsSymbolLayerUtils::encodeSldUom
static QString encodeSldUom(QgsUnitTypes::RenderUnit unit, double *scaleFactor)
Encodes a render unit into an SLD unit of measure string.
Definition: qgssymbollayerutils.cpp:714
QgsGeometry::boundingBox
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Definition: qgsgeometry.cpp:1080
QgsCoordinateTransform::transformPolygon
void transformPolygon(QPolygonF &polygon, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward) const SIP_THROW(QgsCsException)
Transforms a polygon to the destination coordinate system.
Definition: qgscoordinatetransform.cpp:421
qgsgeometrycollection.h
QgsBox3d
A 3-dimensional box composed of x, y, z coordinates.
Definition: qgsbox3d.h:38
QgsGeometry::fromQPolygonF
static QgsGeometry fromQPolygonF(const QPolygonF &polygon)
Construct geometry from a QPolygonF.
Definition: qgsgeometry.cpp:3408
QgsFeature
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:55
QgsPropertyCollection::setProperty
void setProperty(int key, const QgsProperty &property)
Adds a property to the collection and takes ownership of it.
Definition: qgspropertycollection.cpp:187
QgsSymbolRenderContext::renderContext
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
Definition: qgssymbolrendercontext.h:62
QgsPropertyDefinition::Opacity
@ Opacity
Opacity (0-100)
Definition: qgsproperty.h:62
QgsCurve::numPoints
virtual int numPoints() const =0
Returns the number of points in the curve.
qgsgeometrygeneratorsymbollayer.h
QgsSymbolLayer::startRender
virtual void startRender(QgsSymbolRenderContext &context)=0
Called before a set of rendering operations commences on the supplied render context.
qgslogger.h
QgsRenderContext::painter
QPainter * painter()
Returns the destination QPainter for the render operation.
Definition: qgsrendercontext.h:112
QgsCurve::segmentize
QgsCurve * segmentize(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a geometry without curves.
Definition: qgscurve.cpp:175
QgsPaintEffect::enabled
bool enabled() const
Returns whether the effect is enabled.
Definition: qgspainteffect.h:197
QgsSymbol::mForceRHR
bool mForceRHR
Definition: qgssymbol.h:801
QgsRenderContext::setGeometry
void setGeometry(const QgsAbstractGeometry *geometry)
Sets pointer to original (unsegmentized) geometry.
Definition: qgsrendercontext.h:639
QgsSymbol::asImage
QImage asImage(QSize size, QgsRenderContext *customContext=nullptr)
Returns an image of the symbol at the specified size.
Definition: qgssymbol.cpp:1009
QgsExpressionContextScope::StaticVariable
Single variable definition for use within a QgsExpressionContextScope.
Definition: qgsexpressioncontext.h:120
QgsCoordinateTransform
Class for doing transforms between two map coordinate systems.
Definition: qgscoordinatetransform.h:57
QgsSymbol::mAnimationSettings
QgsSymbolAnimationSettings mAnimationSettings
Definition: qgssymbol.h:803
QgsGeometry::type
QgsWkbTypes::GeometryType type
Definition: qgsgeometry.h:128
QgsVectorLayer::clone
QgsVectorLayer * clone() const override
Returns a new instance equivalent to this one.
Definition: qgsvectorlayer.cpp:265
Q_NOWARN_DEPRECATED_PUSH
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:2819
QgsSymbol::_getLineString
static QPolygonF _getLineString(QgsRenderContext &context, const QgsCurve &curve, bool clipToExtent=true)
Creates a line string in screen coordinates from a QgsCurve in map coordinates.
Definition: qgssymbol.cpp:84
QgsRectangle::isEmpty
bool isEmpty() const
Returns true if the rectangle is empty.
Definition: qgsrectangle.h:469
QgsRenderContext::setTextureOrigin
void setTextureOrigin(const QPointF &origin)
Sets the texture origin, which should be used as a brush transform when rendering using QBrush object...
Definition: qgsrendercontext.cpp:645
qgsfillsymbol.h
QgsSymbol::setColor
void setColor(const QColor &color) const
Sets the color for the symbol.
Definition: qgssymbol.cpp:867
qgssymbol.h
QgsAbstractGeometry::nextVertex
virtual bool nextVertex(QgsVertexId &id, QgsPoint &vertex) const =0
Returns next vertex id and coordinates.
QgsPoint::x
double x
Definition: qgspoint.h:69
QgsRectangle::isNull
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:479
QgsGeometry::set
void set(QgsAbstractGeometry *geometry)
Sets the underlying geometry store.
Definition: qgsgeometry.cpp:147
QgsSymbol::stopFeatureRender
void stopFeatureRender(const QgsFeature &feature, QgsRenderContext &context, int layer=-1)
Called after symbol layers have been rendered for a particular feature.
Definition: qgssymbol.cpp:1841
qgsproject.h
QgsSymbol::bigSymbolPreviewImage
QImage bigSymbolPreviewImage(QgsExpressionContext *expressionContext=nullptr, Qgis::SymbolPreviewFlags flags=Qgis::SymbolPreviewFlag::FlagIncludeCrosshairsForMarkerSymbols)
Returns a large (roughly 100x100 pixel) preview image for the symbol.
Definition: qgssymbol.cpp:1024
Qgis::SymbolType::Marker
@ Marker
Marker symbol.
qgsgeos.h
QgsSymbol::canCauseArtifactsBetweenAdjacentTiles
bool canCauseArtifactsBetweenAdjacentTiles() const
Returns true if the symbol rendering can cause visible artifacts across a single feature when the fea...
Definition: qgssymbol.cpp:1186
QgsSymbol::usesMapUnits
bool usesMapUnits() const
Returns true if the symbol has any components which use map unit based sizes.
Definition: qgssymbol.cpp:599
QgsGeometry::collectGeometry
static QgsGeometry collectGeometry(const QVector< QgsGeometry > &geometries)
Creates a new multipart geometry from a list of QgsGeometry objects.
Definition: qgsgeometry.cpp:259
qgslinesymbol.h
QgsMapLayer::type
QgsMapLayerType type
Definition: qgsmaplayer.h:80