QGIS API Documentation  3.14.0-Pi (9f7028fd23)
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"
37 #include "qgsstyle.h"
38 #include "qgspainteffect.h"
39 #include "qgseffectstack.h"
40 #include "qgsvectorlayer.h"
41 #include "qgsfeature.h"
42 #include "qgsgeometry.h"
43 #include "qgsmultipoint.h"
44 #include "qgsgeometrycollection.h"
45 #include "qgslinestring.h"
46 #include "qgspolygon.h"
47 #include "qgsclipper.h"
48 #include "qgsproperty.h"
49 #include "qgscolorschemeregistry.h"
50 #include "qgsapplication.h"
53 #include "qgslegendpatchshape.h"
54 
55 inline
56 QgsProperty rotateWholeSymbol( double additionalRotation, const QgsProperty &property )
57 {
58  QString exprString = property.asExpression();
59  return QgsProperty::fromExpression( QString::number( additionalRotation ) + " + (" + exprString + ')' );
60 }
61 
62 inline
63 QgsProperty scaleWholeSymbol( double scaleFactor, const QgsProperty &property )
64 {
65  QString exprString = property.asExpression();
66  return QgsProperty::fromExpression( QString::number( scaleFactor ) + "*(" + exprString + ')' );
67 }
68 
69 inline
70 QgsProperty scaleWholeSymbol( double scaleFactorX, double scaleFactorY, const QgsProperty &property )
71 {
72  QString exprString = property.asExpression();
74  ( !qgsDoubleNear( scaleFactorX, 0.0 ) ? "tostring(" + QString::number( scaleFactorX ) + "*(" + exprString + "))" : QStringLiteral( "'0'" ) ) +
75  "|| ',' || " +
76  ( !qgsDoubleNear( scaleFactorY, 0.0 ) ? "tostring(" + QString::number( scaleFactorY ) + "*(" + exprString + "))" : QStringLiteral( "'0'" ) ) );
77 }
78 
79 
81 
82 Q_NOWARN_DEPRECATED_PUSH // because of deprecated mLayer
84  : mType( type )
85  , mLayers( layers )
86 {
87 
88  // check they're all correct symbol layers
89  for ( int i = 0; i < mLayers.count(); i++ )
90  {
91  if ( !mLayers.at( i ) )
92  {
93  mLayers.removeAt( i-- );
94  }
95  else if ( !mLayers.at( i )->isCompatibleWithSymbol( this ) )
96  {
97  delete mLayers.at( i );
98  mLayers.removeAt( i-- );
99  }
100  }
101 }
103 
104 QPolygonF QgsSymbol::_getLineString( QgsRenderContext &context, const QgsCurve &curve, bool clipToExtent )
105 {
106  const unsigned int nPoints = curve.numPoints();
107 
109  const QgsMapToPixel &mtp = context.mapToPixel();
110  QPolygonF pts;
111 
112  //apply clipping for large lines to achieve a better rendering performance
113  if ( clipToExtent && nPoints > 1 )
114  {
115  const QgsRectangle &e = context.extent();
116  const double cw = e.width() / 10;
117  const double ch = e.height() / 10;
118  const QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch );
119  pts = QgsClipper::clippedLine( curve, clipRect );
120  }
121  else
122  {
123  pts = curve.asQPolygonF();
124  }
125 
126  //transform the QPolygonF to screen coordinates
127  if ( ct.isValid() )
128  {
129  try
130  {
131  ct.transformPolygon( pts );
132  }
133  catch ( QgsCsException & )
134  {
135  // we don't abort the rendering here, instead we remove any invalid points and just plot those which ARE valid
136  }
137  }
138 
139  // remove non-finite points, e.g. infinite or NaN points caused by reprojecting errors
140  pts.erase( std::remove_if( pts.begin(), pts.end(),
141  []( const QPointF point )
142  {
143  return !std::isfinite( point.x() ) || !std::isfinite( point.y() );
144  } ), pts.end() );
145 
146  QPointF *ptr = pts.data();
147  for ( int i = 0; i < pts.size(); ++i, ++ptr )
148  {
149  mtp.transformInPlace( ptr->rx(), ptr->ry() );
150  }
151 
152  return pts;
153 }
154 
155 QPolygonF QgsSymbol::_getPolygonRing( QgsRenderContext &context, const QgsCurve &curve, const bool clipToExtent, const bool isExteriorRing, const bool correctRingOrientation )
156 {
157  const QgsCoordinateTransform ct = context.coordinateTransform();
158  const QgsMapToPixel &mtp = context.mapToPixel();
159  const QgsRectangle &e = context.extent();
160  const double cw = e.width() / 10;
161  const double ch = e.height() / 10;
162  QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch );
163 
164  QPolygonF poly = curve.asQPolygonF();
165 
166  if ( curve.numPoints() < 1 )
167  return QPolygonF();
168 
169  if ( correctRingOrientation )
170  {
171  // ensure consistent polygon ring orientation
172  if ( isExteriorRing && curve.orientation() != QgsCurve::Clockwise )
173  std::reverse( poly.begin(), poly.end() );
174  else if ( !isExteriorRing && curve.orientation() != QgsCurve::CounterClockwise )
175  std::reverse( poly.begin(), poly.end() );
176  }
177 
178  //clip close to view extent, if needed
179  const QRectF ptsRect = poly.boundingRect();
180  if ( clipToExtent && !context.extent().contains( ptsRect ) )
181  {
182  QgsClipper::trimPolygon( poly, clipRect );
183  }
184 
185  //transform the QPolygonF to screen coordinates
186  if ( ct.isValid() )
187  {
188  try
189  {
190  ct.transformPolygon( poly );
191  }
192  catch ( QgsCsException & )
193  {
194  // we don't abort the rendering here, instead we remove any invalid points and just plot those which ARE valid
195  }
196  }
197 
198  // remove non-finite points, e.g. infinite or NaN points caused by reprojecting errors
199  poly.erase( std::remove_if( poly.begin(), poly.end(),
200  []( const QPointF point )
201  {
202  return !std::isfinite( point.x() ) || !std::isfinite( point.y() );
203  } ), poly.end() );
204 
205  QPointF *ptr = poly.data();
206  for ( int i = 0; i < poly.size(); ++i, ++ptr )
207  {
208  mtp.transformInPlace( ptr->rx(), ptr->ry() );
209  }
210 
211  if ( !poly.empty() && !poly.isClosed() )
212  poly << poly.at( 0 );
213 
214  return poly;
215 }
216 
217 void QgsSymbol::_getPolygon( QPolygonF &pts, QVector<QPolygonF> &holes, QgsRenderContext &context, const QgsPolygon &polygon, const bool clipToExtent, const bool correctRingOrientation )
218 {
219  holes.clear();
220 
221  pts = _getPolygonRing( context, *polygon.exteriorRing(), clipToExtent, true, correctRingOrientation );
222  const int ringCount = polygon.numInteriorRings();
223  holes.reserve( ringCount );
224  for ( int idx = 0; idx < ringCount; idx++ )
225  {
226  const QPolygonF hole = _getPolygonRing( context, *( polygon.interiorRing( idx ) ), clipToExtent, false, correctRingOrientation );
227  if ( !hole.isEmpty() )
228  holes.append( hole );
229  }
230 }
231 
233 {
234  // delete all symbol layers (we own them, so it's okay)
235  qDeleteAll( mLayers );
236 }
237 
239 {
240  if ( mLayers.empty() )
241  {
243  }
244 
245  QgsSymbolLayerList::const_iterator it = mLayers.constBegin();
246 
247  QgsUnitTypes::RenderUnit unit = ( *it )->outputUnit();
248 
249  for ( ; it != mLayers.constEnd(); ++it )
250  {
251  if ( ( *it )->outputUnit() != unit )
252  {
254  }
255  }
256  return unit;
257 }
258 
260 {
261  if ( mLayers.empty() )
262  {
263  return QgsMapUnitScale();
264  }
265 
266  QgsSymbolLayerList::const_iterator it = mLayers.constBegin();
267  if ( it == mLayers.constEnd() )
268  return QgsMapUnitScale();
269 
270  QgsMapUnitScale scale = ( *it )->mapUnitScale();
271  ++it;
272 
273  for ( ; it != mLayers.constEnd(); ++it )
274  {
275  if ( ( *it )->mapUnitScale() != scale )
276  {
277  return QgsMapUnitScale();
278  }
279  }
280  return scale;
281 }
282 
284 {
285  const auto constMLayers = mLayers;
286  for ( QgsSymbolLayer *layer : constMLayers )
287  {
288  layer->setOutputUnit( u );
289  }
290 }
291 
293 {
294  const auto constMLayers = mLayers;
295  for ( QgsSymbolLayer *layer : constMLayers )
296  {
297  layer->setMapUnitScale( scale );
298  }
299 }
300 
302 {
303  std::unique_ptr< QgsSymbol > s;
304 
305  // override global default if project has a default for this type
306  QString defaultSymbol;
307  switch ( geomType )
308  {
310  defaultSymbol = QgsProject::instance()->readEntry( QStringLiteral( "DefaultStyles" ), QStringLiteral( "/Marker" ) );
311  break;
313  defaultSymbol = QgsProject::instance()->readEntry( QStringLiteral( "DefaultStyles" ), QStringLiteral( "/Line" ) );
314  break;
316  defaultSymbol = QgsProject::instance()->readEntry( QStringLiteral( "DefaultStyles" ), QStringLiteral( "/Fill" ) );
317  break;
318  default:
319  break;
320  }
321  if ( !defaultSymbol.isEmpty() )
322  s.reset( QgsStyle::defaultStyle()->symbol( defaultSymbol ) );
323 
324  // if no default found for this type, get global default (as previously)
325  if ( !s )
326  {
327  switch ( geomType )
328  {
330  s = qgis::make_unique< QgsMarkerSymbol >();
331  break;
333  s = qgis::make_unique< QgsLineSymbol >();
334  break;
336  s = qgis::make_unique< QgsFillSymbol >();
337  break;
338  default:
339  QgsDebugMsg( QStringLiteral( "unknown layer's geometry type" ) );
340  return nullptr;
341  }
342  }
343 
344  // set opacity
345  double opacity = 1.0;
346  bool ok = false;
347  // upgrade old setting
348  double alpha = QgsProject::instance()->readDoubleEntry( QStringLiteral( "DefaultStyles" ), QStringLiteral( "/AlphaInt" ), 255, &ok );
349  if ( ok )
350  opacity = alpha / 255.0;
351  double newOpacity = QgsProject::instance()->readDoubleEntry( QStringLiteral( "DefaultStyles" ), QStringLiteral( "/Opacity" ), 1.0, &ok );
352  if ( ok )
353  opacity = newOpacity;
354  s->setOpacity( opacity );
355 
356  // set random color, it project prefs allow
357  if ( defaultSymbol.isEmpty() ||
358  QgsProject::instance()->readBoolEntry( QStringLiteral( "DefaultStyles" ), QStringLiteral( "/RandomColors" ), true ) )
359  {
360  s->setColor( QgsApplication::colorSchemeRegistry()->fetchRandomStyleColor() );
361  }
362 
363  return s.release();
364 }
365 
367 {
368  return mLayers.value( layer );
369 }
370 
371 const QgsSymbolLayer *QgsSymbol::symbolLayer( int layer ) const
372 {
373  return mLayers.value( layer );
374 }
375 
377 {
378  if ( index < 0 || index > mLayers.count() ) // can be added also after the last index
379  return false;
380 
381  if ( !layer || !layer->isCompatibleWithSymbol( this ) )
382  return false;
383 
384  mLayers.insert( index, layer );
385  return true;
386 }
387 
388 
390 {
391  if ( !layer || !layer->isCompatibleWithSymbol( this ) )
392  return false;
393 
394  mLayers.append( layer );
395  return true;
396 }
397 
398 
400 {
401  if ( index < 0 || index >= mLayers.count() )
402  return false;
403 
404  delete mLayers.at( index );
405  mLayers.removeAt( index );
406  return true;
407 }
408 
409 
411 {
412  if ( index < 0 || index >= mLayers.count() )
413  return nullptr;
414 
415  return mLayers.takeAt( index );
416 }
417 
418 
420 {
421  QgsSymbolLayer *oldLayer = mLayers.value( index );
422 
423  if ( oldLayer == layer )
424  return false;
425 
426  if ( !layer || !layer->isCompatibleWithSymbol( this ) )
427  return false;
428 
429  delete oldLayer; // first delete the original layer
430  mLayers[index] = layer; // set new layer
431  return true;
432 }
433 
434 
435 void QgsSymbol::startRender( QgsRenderContext &context, const QgsFields &fields )
436 {
437  Q_ASSERT_X( !mStarted, "startRender", "Rendering has already been started for this symbol instance!" );
438  mStarted = true;
439 
440  mSymbolRenderContext.reset( new QgsSymbolRenderContext( context, QgsUnitTypes::RenderUnknownUnit, mOpacity, false, mRenderHints, nullptr, fields ) );
441 
442  // Why do we need a copy here ? Is it to make sure the symbol layer rendering does not mess with the symbol render context ?
443  // Or is there another profound reason ?
444  QgsSymbolRenderContext symbolContext( context, QgsUnitTypes::RenderUnknownUnit, mOpacity, false, mRenderHints, nullptr, fields );
445 
446  std::unique_ptr< QgsExpressionContextScope > scope( QgsExpressionContextUtils::updateSymbolScope( this, new QgsExpressionContextScope() ) );
447  mSymbolRenderContext->setExpressionContextScope( scope.release() );
448 
449  const auto constMLayers = mLayers;
450  for ( QgsSymbolLayer *layer : constMLayers )
451  {
452  if ( !layer->enabled() || !context.isSymbolLayerEnabled( layer ) )
453  continue;
454 
455  layer->prepareExpressions( symbolContext );
456  layer->startRender( symbolContext );
457  }
458 }
459 
461 {
462  Q_ASSERT_X( mStarted, "startRender", "startRender was not called for this symbol instance!" );
463  mStarted = false;
464 
465  Q_UNUSED( context )
466  if ( mSymbolRenderContext )
467  {
468  const auto constMLayers = mLayers;
469  for ( QgsSymbolLayer *layer : constMLayers )
470  {
471  if ( !layer->enabled() || !context.isSymbolLayerEnabled( layer ) )
472  continue;
473 
474  layer->stopRender( *mSymbolRenderContext );
475  }
476  }
477 
478  mSymbolRenderContext.reset( nullptr );
479 
481  mLayer = nullptr;
483 }
484 
485 void QgsSymbol::setColor( const QColor &color )
486 {
487  const auto constMLayers = mLayers;
488  for ( QgsSymbolLayer *layer : constMLayers )
489  {
490  if ( !layer->isLocked() )
491  layer->setColor( color );
492  }
493 }
494 
495 QColor QgsSymbol::color() const
496 {
497  for ( QgsSymbolLayerList::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
498  {
499  // return color of the first unlocked layer
500  if ( !( *it )->isLocked() )
501  return ( *it )->color();
502  }
503  return QColor( 0, 0, 0 );
504 }
505 
506 void QgsSymbol::drawPreviewIcon( QPainter *painter, QSize size, QgsRenderContext *customContext, bool selected, const QgsExpressionContext *expressionContext, const QgsLegendPatchShape *patchShape )
507 {
508  QgsRenderContext *context = customContext;
509  std::unique_ptr< QgsRenderContext > tempContext;
510  if ( !context )
511  {
512  tempContext.reset( new QgsRenderContext( QgsRenderContext::fromQPainter( painter ) ) );
513  context = tempContext.get();
515  }
516 
517  const bool prevForceVector = context->forceVectorOutput();
518  context->setForceVectorOutput( true );
519  QgsSymbolRenderContext symbolContext( *context, QgsUnitTypes::RenderUnknownUnit, mOpacity, false, mRenderHints, nullptr );
520  symbolContext.setSelected( selected );
522  if ( patchShape )
523  symbolContext.setPatchShape( *patchShape );
524 
525  if ( !customContext && expressionContext )
526  {
527  context->setExpressionContext( *expressionContext );
528  }
529  else if ( !customContext )
530  {
531  // if no render context was passed, build a minimal expression context
532  QgsExpressionContext expContext;
534  context->setExpressionContext( expContext );
535  }
536 
537  for ( QgsSymbolLayer *layer : qgis::as_const( mLayers ) )
538  {
539  if ( !layer->enabled() || ( customContext && !customContext->isSymbolLayerEnabled( layer ) ) )
540  continue;
541 
542  if ( mType == Fill && layer->type() == Line )
543  {
544  // line symbol layer would normally draw just a line
545  // so we override this case to force it to draw a polygon stroke
546  QgsLineSymbolLayer *lsl = dynamic_cast<QgsLineSymbolLayer *>( layer );
547  if ( lsl )
548  {
549  // from QgsFillSymbolLayer::drawPreviewIcon() -- would be nicer to add the
550  // symbol type to QgsSymbolLayer::drawPreviewIcon so this logic could be avoided!
551 
552  // hmm... why was this using size -1 ??
553  const QSizeF targetSize = QSizeF( size.width() - 1, size.height() - 1 );
554 
555  const QList< QList< QPolygonF > > polys = patchShape ? patchShape->toQPolygonF( QgsSymbol::Fill, targetSize )
557 
558  lsl->startRender( symbolContext );
559  QgsPaintEffect *effect = lsl->paintEffect();
560 
561  std::unique_ptr< QgsEffectPainter > effectPainter;
562  if ( effect && effect->enabled() )
563  effectPainter = qgis::make_unique< QgsEffectPainter >( symbolContext.renderContext(), effect );
564 
565  for ( const QList< QPolygonF > &poly : polys )
566  {
567  QVector< QPolygonF > rings;
568  for ( int i = 1; i < poly.size(); ++i )
569  rings << poly.at( i );
570  lsl->renderPolygonStroke( poly.value( 0 ), &rings, symbolContext );
571  }
572 
573  effectPainter.reset();
574  lsl->stopRender( symbolContext );
575  }
576  }
577  else
578  layer->drawPreviewIcon( symbolContext, size );
579  }
580 
581  context->setForceVectorOutput( prevForceVector );
582 }
583 
584 void QgsSymbol::exportImage( const QString &path, const QString &format, QSize size )
585 {
586  if ( format.compare( QLatin1String( "svg" ), Qt::CaseInsensitive ) == 0 )
587  {
588  QSvgGenerator generator;
589  generator.setFileName( path );
590  generator.setSize( size );
591  generator.setViewBox( QRect( 0, 0, size.height(), size.height() ) );
592 
593  QPainter painter( &generator );
594  drawPreviewIcon( &painter, size );
595  painter.end();
596  }
597  else
598  {
599  QImage image = asImage( size );
600  image.save( path );
601  }
602 }
603 
604 QImage QgsSymbol::asImage( QSize size, QgsRenderContext *customContext )
605 {
606  QImage image( size, QImage::Format_ARGB32_Premultiplied );
607  image.fill( 0 );
608 
609  QPainter p( &image );
610  p.setRenderHint( QPainter::Antialiasing );
611 
612  drawPreviewIcon( &p, size, customContext );
613 
614  return image;
615 }
616 
617 
619 {
620  QImage preview( QSize( 100, 100 ), QImage::Format_ARGB32_Premultiplied );
621  preview.fill( 0 );
622 
623  QPainter p( &preview );
624  p.setRenderHint( QPainter::Antialiasing );
625  p.translate( 0.5, 0.5 ); // shift by half a pixel to avoid blurring due antialiasing
626 
627  if ( mType == QgsSymbol::Marker )
628  {
629  p.setPen( QPen( Qt::gray ) );
630  p.drawLine( 0, 50, 100, 50 );
631  p.drawLine( 50, 0, 50, 100 );
632  }
633 
636  if ( expressionContext )
637  context.setExpressionContext( *expressionContext );
638 
639  context.setIsGuiPreview( true );
640  startRender( context );
641 
642  if ( mType == QgsSymbol::Line )
643  {
644  QPolygonF poly;
645  poly << QPointF( 0, 50 ) << QPointF( 99, 50 );
646  static_cast<QgsLineSymbol *>( this )->renderPolyline( poly, nullptr, context );
647  }
648  else if ( mType == QgsSymbol::Fill )
649  {
650  QPolygonF polygon;
651  polygon << QPointF( 20, 20 ) << QPointF( 80, 20 ) << QPointF( 80, 80 ) << QPointF( 20, 80 ) << QPointF( 20, 20 );
652  static_cast<QgsFillSymbol *>( this )->renderPolygon( polygon, nullptr, nullptr, context );
653  }
654  else // marker
655  {
656  static_cast<QgsMarkerSymbol *>( this )->renderPoint( QPointF( 50, 50 ), nullptr, context );
657  }
658 
659  stopRender( context );
660  return preview;
661 }
662 
663 
664 QString QgsSymbol::dump() const
665 {
666  QString t;
667  switch ( type() )
668  {
669  case QgsSymbol::Marker:
670  t = QStringLiteral( "MARKER" );
671  break;
672  case QgsSymbol::Line:
673  t = QStringLiteral( "LINE" );
674  break;
675  case QgsSymbol::Fill:
676  t = QStringLiteral( "FILL" );
677  break;
678  default:
679  Q_ASSERT( false && "unknown symbol type" );
680  }
681  QString s = QStringLiteral( "%1 SYMBOL (%2 layers) color %3" ).arg( t ).arg( mLayers.count() ).arg( QgsSymbolLayerUtils::encodeColor( color() ) );
682 
683  for ( QgsSymbolLayerList::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
684  {
685  // TODO:
686  }
687  return s;
688 }
689 
690 void QgsSymbol::toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const
691 {
692  props[ QStringLiteral( "alpha" )] = QString::number( opacity() );
693  double scaleFactor = 1.0;
694  props[ QStringLiteral( "uom" )] = QgsSymbolLayerUtils::encodeSldUom( outputUnit(), &scaleFactor );
695  props[ QStringLiteral( "uomScale" )] = ( !qgsDoubleNear( scaleFactor, 1.0 ) ? qgsDoubleToString( scaleFactor ) : QString() );
696 
697  for ( QgsSymbolLayerList::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
698  {
699  ( *it )->toSld( doc, element, props );
700  }
701 }
702 
704 {
705  QgsSymbolLayerList lst;
706  for ( QgsSymbolLayerList::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
707  {
708  QgsSymbolLayer *layer = ( *it )->clone();
709  layer->setLocked( ( *it )->isLocked() );
710  layer->setRenderingPass( ( *it )->renderingPass() );
711  layer->setEnabled( ( *it )->enabled() );
712  lst.append( layer );
713  }
714  return lst;
715 }
716 
718 {
719  Q_ASSERT( layer->type() == Hybrid );
720 
721  if ( layer->dataDefinedProperties().hasActiveProperties() && !layer->dataDefinedProperties().valueAsBool( QgsSymbolLayer::PropertyLayerEnabled, context.renderContext().expressionContext(), true ) )
722  return;
723 
724  QgsGeometryGeneratorSymbolLayer *generatorLayer = static_cast<QgsGeometryGeneratorSymbolLayer *>( layer );
725 
726  QgsPaintEffect *effect = generatorLayer->paintEffect();
727  if ( effect && effect->enabled() )
728  {
729  QgsEffectPainter p( context.renderContext(), effect );
730  generatorLayer->render( context );
731  }
732  else
733  {
734  generatorLayer->render( context );
735  }
736 }
737 
738 QSet<QString> QgsSymbol::usedAttributes( const QgsRenderContext &context ) const
739 {
740  QSet<QString> attributes;
741  QgsSymbolLayerList::const_iterator sIt = mLayers.constBegin();
742  for ( ; sIt != mLayers.constEnd(); ++sIt )
743  {
744  if ( *sIt )
745  {
746  attributes.unite( ( *sIt )->usedAttributes( context ) );
747  }
748  }
749  return attributes;
750 }
751 
753 {
754  const auto constMLayers = mLayers;
755  for ( QgsSymbolLayer *layer : constMLayers )
756  {
757  if ( layer->hasDataDefinedProperties() )
758  return true;
759  }
760  return false;
761 }
762 
764 {
766  mLayer = layer;
768 }
769 
771 {
773  return mLayer;
775 }
776 
778 
782 class ExpressionContextScopePopper
783 {
784  public:
785 
786  ExpressionContextScopePopper() = default;
787 
788  ~ExpressionContextScopePopper()
789  {
790  if ( context )
791  context->popScope();
792  }
793 
794  QgsExpressionContext *context = nullptr;
795 };
796 
800 class GeometryRestorer
801 {
802  public:
803  GeometryRestorer( QgsRenderContext &context )
804  : mContext( context ),
805  mGeometry( context.geometry() )
806  {}
807 
808  ~GeometryRestorer()
809  {
810  mContext.setGeometry( mGeometry );
811  }
812 
813  private:
814  QgsRenderContext &mContext;
815  const QgsAbstractGeometry *mGeometry;
816 };
818 
819 void QgsSymbol::renderFeature( const QgsFeature &feature, QgsRenderContext &context, int layer, bool selected, bool drawVertexMarker, int currentVertexMarkerType, double currentVertexMarkerSize )
820 {
821  if ( context.renderingStopped() )
822  return;
823 
824  const QgsGeometry geom = feature.geometry();
825  if ( geom.isNull() )
826  {
827  return;
828  }
829 
830  GeometryRestorer geomRestorer( context );
831  QgsGeometry segmentizedGeometry = geom;
832  bool usingSegmentizedGeometry = false;
833  context.setGeometry( geom.constGet() );
834 
835  bool tileMapRendering = context.testFlag( QgsRenderContext::RenderMapTile );
836 
837  //convert curve types to normal point/line/polygon ones
838  bool needsSegmentizing = QgsWkbTypes::isCurvedType( geom.constGet()->wkbType() ) || geom.constGet()->hasCurvedSegments();
839  if ( !needsSegmentizing )
840  {
841  if ( const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( geom.constGet() ) )
842  {
843  for ( int i = 0; i < collection->numGeometries(); ++i )
844  {
845  if ( QgsWkbTypes::isCurvedType( collection->geometryN( i )->wkbType() ) )
846  {
847  needsSegmentizing = true;
848  break;
849  }
850  }
851  }
852  }
853 
854  if ( needsSegmentizing )
855  {
857  if ( !g )
858  {
859  return;
860  }
861  segmentizedGeometry = QgsGeometry( g );
862  usingSegmentizedGeometry = true;
863  }
864 
865  mSymbolRenderContext->setGeometryPartCount( segmentizedGeometry.constGet()->partCount() );
866  mSymbolRenderContext->setGeometryPartNum( 1 );
867 
868  const bool needsExpressionContext = hasDataDefinedProperties();
869  ExpressionContextScopePopper scopePopper;
870  if ( mSymbolRenderContext->expressionContextScope() )
871  {
872  if ( needsExpressionContext )
873  {
874  // this is somewhat nasty - by appending this scope here it's now owned
875  // by both mSymbolRenderContext AND context.expressionContext()
876  // the RAII scopePopper is required to make sure it always has ownership transferred back
877  // from context.expressionContext(), even if exceptions of other early exits occur in this
878  // function
879  context.expressionContext().appendScope( mSymbolRenderContext->expressionContextScope() );
880  scopePopper.context = &context.expressionContext();
881 
882  QgsExpressionContextUtils::updateSymbolScope( this, mSymbolRenderContext->expressionContextScope() );
883  mSymbolRenderContext->expressionContextScope()->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_PART_COUNT, mSymbolRenderContext->geometryPartCount(), true ) );
884  mSymbolRenderContext->expressionContextScope()->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_PART_NUM, 1, true ) );
885  }
886  }
887 
888  // Collection of markers to paint, only used for no curve types.
889  QPolygonF markers;
890 
891  // Simplify the geometry, if needed.
893  {
894  const int simplifyHints = context.vectorSimplifyMethod().simplifyHints();
895  const QgsMapToPixelSimplifier simplifier( simplifyHints, context.vectorSimplifyMethod().tolerance(),
897  segmentizedGeometry = simplifier.simplify( segmentizedGeometry );
898  }
899 
900  QgsGeometry renderedBoundsGeom;
901 
902  // Step 1 - collect the set of painter coordinate geometries to render.
903  // We do this upfront, because we only want to ever do this once, regardless how many symbol layers we need to render.
904 
905  struct PointInfo
906  {
907  QPointF renderPoint;
908  const QgsPoint *originalGeometry = nullptr;
909  };
910  QVector< PointInfo > pointsToRender;
911 
912  struct LineInfo
913  {
914  QPolygonF renderLine;
915  const QgsCurve *originalGeometry = nullptr;
916  };
917  QVector< LineInfo > linesToRender;
918 
919  struct PolygonInfo
920  {
921  QPolygonF renderExterior;
922  QVector< QPolygonF > renderRings;
923  const QgsPolygon *originalGeometry = nullptr;
924  };
925  QVector< PolygonInfo > polygonsToRender;
926 
927  std::function< void ( const QgsAbstractGeometry * )> getPartGeometry;
928  getPartGeometry = [&pointsToRender, &linesToRender, &polygonsToRender, &getPartGeometry, &context, &tileMapRendering, &markers, &feature, this]( const QgsAbstractGeometry * part )
929  {
930  Q_UNUSED( feature )
931 
932  if ( !part )
933  return;
934 
935  switch ( QgsWkbTypes::flatType( part->wkbType() ) )
936  {
937  case QgsWkbTypes::Point:
938  {
939  if ( mType != QgsSymbol::Marker )
940  {
941  QgsDebugMsgLevel( QStringLiteral( "point can be drawn only with marker symbol!" ), 2 );
942  break;
943  }
944 
945  PointInfo info;
946  info.originalGeometry = qgsgeometry_cast< const QgsPoint * >( part );
947  info.renderPoint = _getPoint( context, *info.originalGeometry );
948  pointsToRender << info;
949  break;
950  }
951 
953  {
954  if ( mType != QgsSymbol::Line )
955  {
956  QgsDebugMsgLevel( QStringLiteral( "linestring can be drawn only with line symbol!" ), 2 );
957  break;
958  }
959 
960  LineInfo info;
961  info.originalGeometry = qgsgeometry_cast<const QgsCurve *>( part );
962  info.renderLine = _getLineString( context, *info.originalGeometry, !tileMapRendering && clipFeaturesToExtent() );
963  linesToRender << info;
964  break;
965  }
966 
969  {
970  QPolygonF pts;
971  QVector<QPolygonF> holes;
972  if ( mType != QgsSymbol::Fill )
973  {
974  QgsDebugMsgLevel( QStringLiteral( "polygon can be drawn only with fill symbol!" ), 2 );
975  break;
976  }
977 
978  PolygonInfo info;
979  info.originalGeometry = qgsgeometry_cast<const QgsPolygon *>( part );
980  if ( !info.originalGeometry->exteriorRing() )
981  {
982  QgsDebugMsg( QStringLiteral( "cannot render polygon with no exterior ring" ) );
983  break;
984  }
985 
986  _getPolygon( info.renderExterior, info.renderRings, context, *info.originalGeometry, !tileMapRendering && clipFeaturesToExtent(), mForceRHR );
987  polygonsToRender << info;
988  break;
989  }
990 
992  {
993  const QgsMultiPoint *mp = qgsgeometry_cast< const QgsMultiPoint * >( part );
994  markers.reserve( mp->numGeometries() );
995  }
1000  {
1001  const QgsGeometryCollection *geomCollection = qgsgeometry_cast<const QgsGeometryCollection *>( part );
1002 
1003  const unsigned int num = geomCollection->numGeometries();
1004  for ( unsigned int i = 0; i < num; ++i )
1005  {
1006  if ( context.renderingStopped() )
1007  break;
1008 
1009  getPartGeometry( geomCollection->geometryN( i ) );
1010  }
1011  break;
1012  }
1013 
1016  {
1017  if ( mType != QgsSymbol::Fill )
1018  {
1019  QgsDebugMsgLevel( QStringLiteral( "multi-polygon can be drawn only with fill symbol!" ), 2 );
1020  break;
1021  }
1022 
1023  QPolygonF pts;
1024  QVector<QPolygonF> holes;
1025 
1026  const QgsGeometryCollection *geomCollection = dynamic_cast<const QgsGeometryCollection *>( part );
1027  const unsigned int num = geomCollection->numGeometries();
1028 
1029  // Sort components by approximate area (probably a bit faster than using
1030  // area() )
1031  std::map<double, QList<unsigned int> > thisAreaToPartNum;
1032  for ( unsigned int i = 0; i < num; ++i )
1033  {
1034  const QgsPolygon *polygon = qgsgeometry_cast<const QgsPolygon *>( geomCollection->geometryN( i ) );
1035  const QgsRectangle r( polygon->boundingBox() );
1036  thisAreaToPartNum[ r.width() * r.height()] << i;
1037  }
1038 
1039  // Draw starting with larger parts down to smaller parts, so that in
1040  // case of a part being incorrectly inside another part, it is drawn
1041  // on top of it (#15419)
1042  std::map<double, QList<unsigned int> >::const_reverse_iterator iter = thisAreaToPartNum.rbegin();
1043  for ( ; iter != thisAreaToPartNum.rend(); ++iter )
1044  {
1045  const QList<unsigned int> &listPartIndex = iter->second;
1046  for ( int idx = 0; idx < listPartIndex.size(); ++idx )
1047  {
1048  const unsigned i = listPartIndex[idx];
1049  const QgsPolygon *polygon = qgsgeometry_cast<const QgsPolygon *>( geomCollection->geometryN( i ) );
1050  getPartGeometry( polygon );
1051  }
1052  }
1053  break;
1054  }
1055 
1056  default:
1057  QgsDebugMsg( QStringLiteral( "feature %1: unsupported wkb type %2/%3 for rendering" )
1058  .arg( feature.id() )
1059  .arg( QgsWkbTypes::displayString( part->wkbType() ) )
1060  .arg( part->wkbType(), 0, 16 ) );
1061  }
1062  };
1063 
1064  getPartGeometry( segmentizedGeometry.constGet() );
1065 
1066  // step 2 - determine which layers to render
1067  std::vector< int > layers;
1068  if ( layer == -1 )
1069  {
1070  layers.reserve( mLayers.count() );
1071  for ( int i = 0; i < mLayers.count(); ++i )
1072  layers.emplace_back( i );
1073  }
1074  else
1075  {
1076  layers.emplace_back( layer );
1077  }
1078 
1079  // step 3 - render these geometries using the desired symbol layers.
1080 
1081  if ( needsExpressionContext )
1082  mSymbolRenderContext->expressionContextScope()->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "symbol_layer_count" ), mLayers.count(), true ) );
1083 
1084  for ( const int symbolLayerIndex : layers )
1085  {
1086  QgsSymbolLayer *symbolLayer = mLayers.value( symbolLayerIndex );
1087  if ( !symbolLayer || !symbolLayer->enabled() )
1088  continue;
1089 
1090  if ( needsExpressionContext )
1091  mSymbolRenderContext->expressionContextScope()->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "symbol_layer_index" ), symbolLayerIndex + 1, true ) );
1092 
1093  symbolLayer->startFeatureRender( feature, context );
1094 
1095  switch ( mType )
1096  {
1097  case QgsSymbol::Marker:
1098  {
1099  int geometryPartNumber = 0;
1100  for ( const PointInfo &point : qgis::as_const( pointsToRender ) )
1101  {
1102  if ( context.renderingStopped() )
1103  break;
1104 
1105  mSymbolRenderContext->setGeometryPartNum( geometryPartNumber + 1 );
1106  if ( needsExpressionContext )
1107  mSymbolRenderContext->expressionContextScope()->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_PART_NUM, geometryPartNumber + 1, true ) );
1108 
1109  static_cast<QgsMarkerSymbol *>( this )->renderPoint( point.renderPoint, &feature, context, symbolLayerIndex, selected );
1110  geometryPartNumber++;
1111  }
1112 
1113  break;
1114  }
1115 
1116  case QgsSymbol::Line:
1117  {
1118  if ( linesToRender.empty() )
1119  break;
1120 
1121  int geometryPartNumber = 0;
1122  for ( const LineInfo &line : linesToRender )
1123  {
1124  if ( context.renderingStopped() )
1125  break;
1126 
1127  mSymbolRenderContext->setGeometryPartNum( geometryPartNumber + 1 );
1128  if ( needsExpressionContext )
1129  mSymbolRenderContext->expressionContextScope()->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_PART_NUM, geometryPartNumber + 1, true ) );
1130 
1131  context.setGeometry( line.originalGeometry );
1132  static_cast<QgsLineSymbol *>( this )->renderPolyline( line.renderLine, &feature, context, symbolLayerIndex, selected );
1133  geometryPartNumber++;
1134  }
1135  break;
1136  }
1137 
1138  case QgsSymbol::Fill:
1139  {
1140  int geometryPartNumber = 0;
1141  for ( const PolygonInfo &info : polygonsToRender )
1142  {
1143  if ( context.renderingStopped() )
1144  break;
1145 
1146  mSymbolRenderContext->setGeometryPartNum( geometryPartNumber + 1 );
1147  if ( needsExpressionContext )
1148  mSymbolRenderContext->expressionContextScope()->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_PART_NUM, geometryPartNumber + 1, true ) );
1149 
1150  context.setGeometry( info.originalGeometry );
1151  static_cast<QgsFillSymbol *>( this )->renderPolygon( info.renderExterior, ( !info.renderRings.isEmpty() ? &info.renderRings : nullptr ), &feature, context, symbolLayerIndex, selected );
1152  geometryPartNumber++;
1153  }
1154 
1155  break;
1156  }
1157 
1158  case QgsSymbol::Hybrid:
1159  break;
1160  }
1161 
1162  symbolLayer->stopFeatureRender( feature, context );
1163  }
1164 
1165  // step 4 - handle post processing steps
1166  switch ( mType )
1167  {
1168  case QgsSymbol::Marker:
1169  {
1170  markers.reserve( pointsToRender.size() );
1171  for ( const PointInfo &info : qgis::as_const( pointsToRender ) )
1172  {
1173  if ( context.hasRenderedFeatureHandlers() || context.testFlag( QgsRenderContext::DrawSymbolBounds ) )
1174  {
1175  const QRectF bounds = static_cast<QgsMarkerSymbol *>( this )->bounds( info.renderPoint, context, feature );
1176  if ( context.hasRenderedFeatureHandlers() )
1177  {
1178  renderedBoundsGeom = renderedBoundsGeom.isNull() ? QgsGeometry::fromRect( bounds )
1179  : QgsGeometry::collectGeometry( QVector< QgsGeometry>() << QgsGeometry::fromRect( QgsRectangle( bounds ) ) << renderedBoundsGeom );
1180  }
1181  if ( context.testFlag( QgsRenderContext::DrawSymbolBounds ) )
1182  {
1183  //draw debugging rect
1184  context.painter()->setPen( Qt::red );
1185  context.painter()->setBrush( QColor( 255, 0, 0, 100 ) );
1186  context.painter()->drawRect( bounds );
1187  }
1188  }
1189 
1190  if ( drawVertexMarker && !usingSegmentizedGeometry )
1191  {
1192  markers.append( info.renderPoint );
1193  }
1194  }
1195  break;
1196  }
1197 
1198  case QgsSymbol::Line:
1199  {
1200  for ( const LineInfo &info : qgis::as_const( linesToRender ) )
1201  {
1202  if ( context.hasRenderedFeatureHandlers() )
1203  {
1204  renderedBoundsGeom = renderedBoundsGeom.isNull() ? QgsGeometry::fromQPolygonF( info.renderLine )
1205  : QgsGeometry::collectGeometry( QVector< QgsGeometry>() << QgsGeometry::fromQPolygonF( info.renderLine ) << renderedBoundsGeom );
1206  }
1207 
1208  if ( drawVertexMarker && !usingSegmentizedGeometry )
1209  {
1210  markers << info.renderLine;
1211  }
1212  }
1213  break;
1214  }
1215 
1216  case QgsSymbol::Fill:
1217  {
1218  int i = 0;
1219  for ( const PolygonInfo &info : qgis::as_const( polygonsToRender ) )
1220  {
1221  if ( context.hasRenderedFeatureHandlers() )
1222  {
1223  renderedBoundsGeom = renderedBoundsGeom.isNull() ? QgsGeometry::fromQPolygonF( info.renderExterior )
1224  : QgsGeometry::collectGeometry( QVector< QgsGeometry>() << QgsGeometry::fromQPolygonF( info.renderExterior ) << renderedBoundsGeom );
1225  // TODO: consider holes?
1226  }
1227 
1228  if ( drawVertexMarker && !usingSegmentizedGeometry )
1229  {
1230  markers << info.renderExterior;
1231 
1232  for ( const QPolygonF &hole : info.renderRings )
1233  {
1234  markers << hole;
1235  }
1236  }
1237  i++;
1238  }
1239  break;
1240  }
1241 
1242  case QgsSymbol::Hybrid:
1243  break;
1244  }
1245 
1246  if ( context.hasRenderedFeatureHandlers() )
1247  {
1249  const QList< QgsRenderedFeatureHandlerInterface * > handlers = context.renderedFeatureHandlers();
1250  for ( QgsRenderedFeatureHandlerInterface *handler : handlers )
1251  handler->handleRenderedFeature( feature, renderedBoundsGeom, featureContext );
1252  }
1253 
1254  if ( drawVertexMarker )
1255  {
1256  if ( !markers.isEmpty() && !context.renderingStopped() )
1257  {
1258  const auto constMarkers = markers;
1259  for ( QPointF marker : constMarkers )
1260  {
1261  renderVertexMarker( marker, context, currentVertexMarkerType, currentVertexMarkerSize );
1262  }
1263  }
1264  else
1265  {
1266  QgsCoordinateTransform ct = context.coordinateTransform();
1267  const QgsMapToPixel &mtp = context.mapToPixel();
1268 
1269  QgsPoint vertexPoint;
1270  QgsVertexId vertexId;
1271  double x, y, z;
1272  QPointF mapPoint;
1273  while ( geom.constGet()->nextVertex( vertexId, vertexPoint ) )
1274  {
1275  //transform
1276  x = vertexPoint.x();
1277  y = vertexPoint.y();
1278  z = 0.0;
1279  if ( ct.isValid() )
1280  {
1281  ct.transformInPlace( x, y, z );
1282  }
1283  mapPoint.setX( x );
1284  mapPoint.setY( y );
1285  mtp.transformInPlace( mapPoint.rx(), mapPoint.ry() );
1286  renderVertexMarker( mapPoint, context, currentVertexMarkerType, currentVertexMarkerSize );
1287  }
1288  }
1289  }
1290 }
1291 
1293 {
1294  return mSymbolRenderContext.get();
1295 }
1296 
1297 void QgsSymbol::renderVertexMarker( QPointF pt, QgsRenderContext &context, int currentVertexMarkerType, double currentVertexMarkerSize )
1298 {
1299  int markerSize = context.convertToPainterUnits( currentVertexMarkerSize, QgsUnitTypes::RenderMillimeters );
1300  QgsSymbolLayerUtils::drawVertexMarker( pt.x(), pt.y(), *context.painter(), static_cast< QgsSymbolLayerUtils::VertexMarkerType >( currentVertexMarkerType ), markerSize );
1301 }
1302 
1303 void QgsSymbol::startFeatureRender( const QgsFeature &feature, QgsRenderContext &context, const int layer )
1304 {
1305  if ( layer != -1 )
1306  {
1308  if ( symbolLayer && symbolLayer->enabled() )
1309  {
1310  symbolLayer->startFeatureRender( feature, context );
1311  }
1312  return;
1313  }
1314  else
1315  {
1316  const QList< QgsSymbolLayer * > layers = mLayers;
1317  for ( QgsSymbolLayer *symbolLayer : layers )
1318  {
1319  if ( !symbolLayer->enabled() )
1320  continue;
1321 
1322  symbolLayer->startFeatureRender( feature, context );
1323  }
1324  }
1325 }
1326 
1327 void QgsSymbol::stopFeatureRender( const QgsFeature &feature, QgsRenderContext &context, int layer )
1328 {
1329  if ( layer != -1 )
1330  {
1332  if ( symbolLayer && symbolLayer->enabled() )
1333  {
1334  symbolLayer->stopFeatureRender( feature, context );
1335  }
1336  return;
1337  }
1338  else
1339  {
1340  const QList< QgsSymbolLayer * > layers = mLayers;
1341  for ( QgsSymbolLayer *symbolLayer : layers )
1342  {
1343  if ( !symbolLayer->enabled() )
1344  continue;
1345 
1346  symbolLayer->stopFeatureRender( feature, context );
1347  }
1348  }
1349 }
1350 
1352 
1353 
1354 QgsSymbolRenderContext::QgsSymbolRenderContext( QgsRenderContext &c, QgsUnitTypes::RenderUnit u, qreal opacity, bool selected, QgsSymbol::RenderHints renderHints, const QgsFeature *f, const QgsFields &fields, const QgsMapUnitScale &mapUnitScale )
1355  : mRenderContext( c )
1356  , mOutputUnit( u )
1357  , mMapUnitScale( mapUnitScale )
1358  , mOpacity( opacity )
1359  , mSelected( selected )
1360  , mRenderHints( renderHints )
1361  , mFeature( f )
1362  , mFields( fields )
1363  , mGeometryPartCount( 0 )
1364  , mGeometryPartNum( 0 )
1365 {
1366 }
1367 
1369 
1371 {
1372  mRenderContext.expressionContext().setOriginalValueVariable( value );
1373 }
1374 
1375 double QgsSymbolRenderContext::outputLineWidth( double width ) const
1376 {
1377  return mRenderContext.convertToPainterUnits( width, mOutputUnit, mMapUnitScale );
1378 }
1379 
1380 double QgsSymbolRenderContext::outputPixelSize( double size ) const
1381 {
1382  return mRenderContext.convertToPainterUnits( size, mOutputUnit, mMapUnitScale );
1383 }
1384 
1385 // cppcheck-suppress operatorEqVarError
1387 {
1388  // This is just a dummy implementation of assignment.
1389  // sip 4.7 generates a piece of code that needs this function to exist.
1390  // It's not generated automatically by the compiler because of
1391  // mRenderContext member which is a reference (and thus can't be changed).
1392  Q_ASSERT( false );
1393  return *this;
1394 }
1395 
1397 {
1398  return mExpressionContextScope.get();
1399 }
1400 
1402 {
1403  mExpressionContextScope.reset( contextScope );
1404 }
1405 
1407 {
1408  return mPatchShape.get();
1409 }
1410 
1412 {
1413  mPatchShape.reset( new QgsLegendPatchShape( patchShape ) );
1414 }
1415 
1417 
1419 {
1421  if ( !sl )
1422  return nullptr;
1423 
1424  QgsSymbolLayerList layers;
1425  layers.append( sl );
1426  return new QgsMarkerSymbol( layers );
1427 }
1428 
1430 {
1432  if ( !sl )
1433  return nullptr;
1434 
1435  QgsSymbolLayerList layers;
1436  layers.append( sl );
1437  return new QgsLineSymbol( layers );
1438 }
1439 
1441 {
1443  if ( !sl )
1444  return nullptr;
1445 
1446  QgsSymbolLayerList layers;
1447  layers.append( sl );
1448  return new QgsFillSymbol( layers );
1449 }
1450 
1452 
1454  : QgsSymbol( Marker, layers )
1455 {
1456  if ( mLayers.isEmpty() )
1457  mLayers.append( new QgsSimpleMarkerSymbolLayer() );
1458 }
1459 
1460 void QgsMarkerSymbol::setAngle( double symbolAngle )
1461 {
1462  double origAngle = angle();
1463  double angleDiff = symbolAngle - origAngle;
1464  const auto constMLayers = mLayers;
1465  for ( QgsSymbolLayer *layer : constMLayers )
1466  {
1467  QgsMarkerSymbolLayer *markerLayer = dynamic_cast<QgsMarkerSymbolLayer *>( layer );
1468  if ( markerLayer )
1469  markerLayer->setAngle( markerLayer->angle() + angleDiff );
1470  }
1471 }
1472 
1474 {
1475  for ( QgsSymbolLayer *layer : qgis::as_const( mLayers ) )
1476  {
1477  if ( layer->type() != QgsSymbol::Marker )
1478  continue;
1479  const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
1480  return markerLayer->angle();
1481  }
1482  return 0;
1483 }
1484 
1485 void QgsMarkerSymbol::setLineAngle( double lineAng )
1486 {
1487  const auto constMLayers = mLayers;
1488  for ( QgsSymbolLayer *layer : constMLayers )
1489  {
1490  if ( layer->type() != QgsSymbol::Marker )
1491  continue;
1492  QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( layer );
1493  markerLayer->setLineAngle( lineAng );
1494  }
1495 }
1496 
1498 {
1499  const double symbolRotation = angle();
1500 
1501 
1502  for ( QgsSymbolLayer *layer : qgis::as_const( mLayers ) )
1503  {
1504  if ( layer->type() != QgsSymbol::Marker )
1505  continue;
1506  const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
1507  if ( !property )
1508  {
1509  layer->setDataDefinedProperty( QgsSymbolLayer::PropertyAngle, QgsProperty() );
1510  }
1511  else
1512  {
1513  if ( qgsDoubleNear( markerLayer->angle(), symbolRotation ) )
1514  {
1515  layer->setDataDefinedProperty( QgsSymbolLayer::PropertyAngle, property );
1516  }
1517  else
1518  {
1519  QgsProperty rotatedDD = rotateWholeSymbol( markerLayer->angle() - symbolRotation, property );
1520  layer->setDataDefinedProperty( QgsSymbolLayer::PropertyAngle, rotatedDD );
1521  }
1522  }
1523  }
1524 }
1525 
1527 {
1528  const double symbolRotation = angle();
1529  QgsProperty symbolDD;
1530 
1531  // find the base of the "en masse" pattern
1532  const auto layers = mLayers;
1533  for ( QgsSymbolLayer *layer : layers )
1534  {
1535  if ( layer->type() != QgsSymbol::Marker )
1536  continue;
1537  const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
1538  if ( qgsDoubleNear( markerLayer->angle(), symbolRotation ) && markerLayer->dataDefinedProperties().isActive( QgsSymbolLayer::PropertyAngle ) )
1539  {
1540  symbolDD = markerLayer->dataDefinedProperties().property( QgsSymbolLayer::PropertyAngle );
1541  break;
1542  }
1543  }
1544 
1545  if ( !symbolDD )
1546  return QgsProperty();
1547 
1548  // check that all layer's angle expressions match the "en masse" pattern
1549  for ( QgsSymbolLayer *layer : layers )
1550  {
1551  if ( layer->type() != QgsSymbol::Marker )
1552  continue;
1553  const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
1554 
1556 
1557  if ( qgsDoubleNear( markerLayer->angle(), symbolRotation ) )
1558  {
1559  if ( !layerAngleDD || layerAngleDD != symbolDD )
1560  return QgsProperty();
1561  }
1562  else
1563  {
1564  QgsProperty rotatedDD( rotateWholeSymbol( markerLayer->angle() - symbolRotation, symbolDD ) );
1565  if ( !layerAngleDD || layerAngleDD != rotatedDD )
1566  return QgsProperty();
1567  }
1568  }
1569  return symbolDD;
1570 }
1571 
1572 
1574 {
1575  double origSize = size();
1576 
1577  const auto constMLayers = mLayers;
1578  for ( QgsSymbolLayer *layer : constMLayers )
1579  {
1580  if ( layer->type() != QgsSymbol::Marker )
1581  continue;
1582  QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( layer );
1583  if ( qgsDoubleNear( markerLayer->size(), origSize ) )
1584  markerLayer->setSize( s );
1585  else if ( !qgsDoubleNear( origSize, 0.0 ) )
1586  {
1587  // proportionally scale size
1588  markerLayer->setSize( markerLayer->size() * s / origSize );
1589  }
1590  // also scale offset to maintain relative position
1591  if ( !qgsDoubleNear( origSize, 0.0 ) && ( !qgsDoubleNear( markerLayer->offset().x(), 0.0 ) || !qgsDoubleNear( markerLayer->offset().y(), 0.0 ) ) )
1592  markerLayer->setOffset( QPointF( markerLayer->offset().x() * s / origSize,
1593  markerLayer->offset().y() * s / origSize ) );
1594  }
1595 }
1596 
1598 {
1599  // return size of the largest symbol
1600  double maxSize = 0;
1601  const auto constMLayers = mLayers;
1602  for ( QgsSymbolLayer *layer : constMLayers )
1603  {
1604  if ( layer->type() != QgsSymbol::Marker )
1605  continue;
1606  const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
1607  double lsize = markerLayer->size();
1608  if ( lsize > maxSize )
1609  maxSize = lsize;
1610  }
1611  return maxSize;
1612 }
1613 
1614 double QgsMarkerSymbol::size( const QgsRenderContext &context ) const
1615 {
1616  // return size of the largest symbol
1617  double maxSize = 0;
1618  for ( QgsSymbolLayer *layer : mLayers )
1619  {
1620  if ( layer->type() != QgsSymbol::Marker )
1621  continue;
1622  const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
1623  const double layerSize = context.convertToPainterUnits( markerLayer->size(), markerLayer->sizeUnit(), markerLayer->sizeMapUnitScale() );
1624  maxSize = std::max( maxSize, layerSize );
1625  }
1626  return maxSize;
1627 }
1628 
1630 {
1631  const auto constMLayers = mLayers;
1632  for ( QgsSymbolLayer *layer : constMLayers )
1633  {
1634  if ( layer->type() != QgsSymbol::Marker )
1635  continue;
1636 
1637  QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( layer );
1638  markerLayer->setSizeUnit( unit );
1639  }
1640 }
1641 
1643 {
1644  bool first = true;
1646 
1647  const auto constMLayers = mLayers;
1648  for ( QgsSymbolLayer *layer : constMLayers )
1649  {
1650  if ( layer->type() != QgsSymbol::Marker )
1651  continue;
1652  const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
1653 
1654  if ( first )
1655  unit = markerLayer->sizeUnit();
1656  else
1657  {
1658  if ( unit != markerLayer->sizeUnit() )
1660  }
1661 
1662  first = false;
1663  }
1664  return unit;
1665 }
1666 
1668 {
1669  const auto constMLayers = mLayers;
1670  for ( QgsSymbolLayer *layer : constMLayers )
1671  {
1672  if ( layer->type() != QgsSymbol::Marker )
1673  continue;
1674 
1675  QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( layer );
1676  markerLayer->setSizeMapUnitScale( scale );
1677  }
1678 }
1679 
1681 {
1682  const auto constMLayers = mLayers;
1683  for ( QgsSymbolLayer *layer : constMLayers )
1684  {
1685  if ( layer->type() != QgsSymbol::Marker )
1686  continue;
1687 
1688  QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( layer );
1689  return markerLayer->sizeMapUnitScale();
1690  }
1691  return QgsMapUnitScale();
1692 }
1693 
1695 {
1696  const double symbolSize = size();
1697 
1698  const auto constMLayers = mLayers;
1699  for ( QgsSymbolLayer *layer : constMLayers )
1700  {
1701  if ( layer->type() != QgsSymbol::Marker )
1702  continue;
1703  QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( layer );
1704 
1705  if ( !property )
1706  {
1709  }
1710  else
1711  {
1712  if ( qgsDoubleNear( symbolSize, 0.0 ) || qgsDoubleNear( markerLayer->size(), symbolSize ) )
1713  {
1714  markerLayer->setDataDefinedProperty( QgsSymbolLayer::PropertySize, property );
1715  }
1716  else
1717  {
1718  markerLayer->setDataDefinedProperty( QgsSymbolLayer::PropertySize, scaleWholeSymbol( markerLayer->size() / symbolSize, property ) );
1719  }
1720 
1721  if ( !qgsDoubleNear( markerLayer->offset().x(), 0.0 ) || !qgsDoubleNear( markerLayer->offset().y(), 0.0 ) )
1722  {
1724  markerLayer->offset().x() / symbolSize,
1725  markerLayer->offset().y() / symbolSize, property ) );
1726  }
1727  }
1728  }
1729 }
1730 
1732 {
1733  const double symbolSize = size();
1734 
1735  QgsProperty symbolDD;
1736 
1737  // find the base of the "en masse" pattern
1738  const auto layers = mLayers;
1739  for ( QgsSymbolLayer *layer : layers )
1740  {
1741  if ( layer->type() != QgsSymbol::Marker )
1742  continue;
1743  const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
1744  if ( qgsDoubleNear( markerLayer->size(), symbolSize ) && markerLayer->dataDefinedProperties().isActive( QgsSymbolLayer::PropertySize ) )
1745  {
1746  symbolDD = markerLayer->dataDefinedProperties().property( QgsSymbolLayer::PropertySize );
1747  break;
1748  }
1749  }
1750 
1751  if ( !symbolDD )
1752  return QgsProperty();
1753 
1754  // check that all layers size expressions match the "en masse" pattern
1755  for ( QgsSymbolLayer *layer : layers )
1756  {
1757  if ( layer->type() != QgsSymbol::Marker )
1758  continue;
1759  const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
1760 
1763 
1764  if ( qgsDoubleNear( markerLayer->size(), symbolSize ) )
1765  {
1766  if ( !layerSizeDD || layerSizeDD != symbolDD )
1767  return QgsProperty();
1768  }
1769  else
1770  {
1771  if ( qgsDoubleNear( symbolSize, 0.0 ) )
1772  return QgsProperty();
1773 
1774  QgsProperty scaledDD( scaleWholeSymbol( markerLayer->size() / symbolSize, symbolDD ) );
1775  if ( !layerSizeDD || layerSizeDD != scaledDD )
1776  return QgsProperty();
1777  }
1778 
1779  QgsProperty scaledOffsetDD( scaleWholeSymbol( markerLayer->offset().x() / symbolSize, markerLayer->offset().y() / symbolSize, symbolDD ) );
1780  if ( layerOffsetDD && layerOffsetDD != scaledOffsetDD )
1781  return QgsProperty();
1782  }
1783 
1784  return symbolDD;
1785 }
1786 
1788 {
1789  const auto constMLayers = mLayers;
1790  for ( QgsSymbolLayer *layer : constMLayers )
1791  {
1792  if ( layer->type() != QgsSymbol::Marker )
1793  continue;
1794  QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( layer );
1795  markerLayer->setScaleMethod( scaleMethod );
1796  }
1797 }
1798 
1800 {
1801  const auto constMLayers = mLayers;
1802  for ( QgsSymbolLayer *layer : constMLayers )
1803  {
1804  if ( layer->type() != QgsSymbol::Marker )
1805  continue;
1806  const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
1807  // return scale method of the first symbol layer
1808  return markerLayer->scaleMethod();
1809  }
1810 
1811  return DEFAULT_SCALE_METHOD;
1812 }
1813 
1814 void QgsMarkerSymbol::renderPointUsingLayer( QgsMarkerSymbolLayer *layer, QPointF point, QgsSymbolRenderContext &context )
1815 {
1816  static QPointF nullPoint( 0, 0 );
1817 
1818  if ( layer->dataDefinedProperties().hasActiveProperties() && !layer->dataDefinedProperties().valueAsBool( QgsSymbolLayer::PropertyLayerEnabled, context.renderContext().expressionContext(), true ) )
1819  return;
1820 
1821  QgsPaintEffect *effect = layer->paintEffect();
1822  if ( effect && effect->enabled() )
1823  {
1824  QgsEffectPainter p( context.renderContext() );
1825  p->translate( point );
1826  p.setEffect( effect );
1827  layer->renderPoint( nullPoint, context );
1828  }
1829  else
1830  {
1831  layer->renderPoint( point, context );
1832  }
1833 }
1834 
1835 void QgsMarkerSymbol::renderPoint( QPointF point, const QgsFeature *f, QgsRenderContext &context, int layerIdx, bool selected )
1836 {
1837  QgsSymbolRenderContext symbolContext( context, QgsUnitTypes::RenderUnknownUnit, mOpacity, selected, mRenderHints, f );
1838  symbolContext.setGeometryPartCount( symbolRenderContext()->geometryPartCount() );
1839  symbolContext.setGeometryPartNum( symbolRenderContext()->geometryPartNum() );
1840 
1841  if ( layerIdx != -1 )
1842  {
1843  QgsSymbolLayer *symbolLayer = mLayers.value( layerIdx );
1845  {
1846  if ( symbolLayer->type() == QgsSymbol::Marker )
1847  {
1848  QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( symbolLayer );
1849  renderPointUsingLayer( markerLayer, point, symbolContext );
1850  }
1851  else
1852  renderUsingLayer( symbolLayer, symbolContext );
1853  }
1854  return;
1855  }
1856 
1857 
1858  for ( QgsSymbolLayer *symbolLayer : qgis::as_const( mLayers ) )
1859  {
1860  if ( context.renderingStopped() )
1861  break;
1862 
1863  if ( !symbolLayer->enabled() || !context.isSymbolLayerEnabled( symbolLayer ) )
1864  continue;
1865 
1866  if ( symbolLayer->type() == QgsSymbol::Marker )
1867  {
1868  QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( symbolLayer );
1869  renderPointUsingLayer( markerLayer, point, symbolContext );
1870  }
1871  else
1872  renderUsingLayer( symbolLayer, symbolContext );
1873  }
1874 }
1875 
1876 QRectF QgsMarkerSymbol::bounds( QPointF point, QgsRenderContext &context, const QgsFeature &feature ) const
1877 {
1878  QgsSymbolRenderContext symbolContext( context, QgsUnitTypes::RenderUnknownUnit, mOpacity, false, mRenderHints, &feature, feature.fields() );
1879 
1880  QRectF bound;
1881  const auto constMLayers = mLayers;
1882  for ( QgsSymbolLayer *layer : constMLayers )
1883  {
1884  if ( layer->type() == QgsSymbol::Marker )
1885  {
1887  if ( bound.isNull() )
1888  bound = symbolLayer->bounds( point, symbolContext );
1889  else
1890  bound = bound.united( symbolLayer->bounds( point, symbolContext ) );
1891  }
1892  }
1893  return bound;
1894 }
1895 
1897 {
1898  QgsMarkerSymbol *cloneSymbol = new QgsMarkerSymbol( cloneLayers() );
1899  cloneSymbol->setOpacity( mOpacity );
1901  cloneSymbol->setLayer( mLayer );
1904  cloneSymbol->setForceRHR( mForceRHR );
1905  return cloneSymbol;
1906 }
1907 
1908 
1910 // LINE
1911 
1913  : QgsSymbol( Line, layers )
1914 {
1915  if ( mLayers.isEmpty() )
1916  mLayers.append( new QgsSimpleLineSymbolLayer() );
1917 }
1918 
1919 void QgsLineSymbol::setWidth( double w )
1920 {
1921  double origWidth = width();
1922 
1923  const auto constMLayers = mLayers;
1924  for ( QgsSymbolLayer *layer : constMLayers )
1925  {
1926  QgsLineSymbolLayer *lineLayer = dynamic_cast<QgsLineSymbolLayer *>( layer );
1927 
1928  if ( lineLayer )
1929  {
1930  if ( qgsDoubleNear( lineLayer->width(), origWidth ) )
1931  {
1932  lineLayer->setWidth( w );
1933  }
1934  else if ( !qgsDoubleNear( origWidth, 0.0 ) )
1935  {
1936  // proportionally scale the width
1937  lineLayer->setWidth( lineLayer->width() * w / origWidth );
1938  }
1939  // also scale offset to maintain relative position
1940  if ( !qgsDoubleNear( origWidth, 0.0 ) && !qgsDoubleNear( lineLayer->offset(), 0.0 ) )
1941  lineLayer->setOffset( lineLayer->offset() * w / origWidth );
1942  }
1943  }
1944 }
1945 
1946 double QgsLineSymbol::width() const
1947 {
1948  double maxWidth = 0;
1949  if ( mLayers.isEmpty() )
1950  return maxWidth;
1951 
1952  const auto constMLayers = mLayers;
1953  for ( QgsSymbolLayer *symbolLayer : constMLayers )
1954  {
1955  const QgsLineSymbolLayer *lineLayer = dynamic_cast<QgsLineSymbolLayer *>( symbolLayer );
1956  if ( lineLayer )
1957  {
1958  double width = lineLayer->width();
1959  if ( width > maxWidth )
1960  maxWidth = width;
1961  }
1962  }
1963  return maxWidth;
1964 }
1965 
1966 double QgsLineSymbol::width( const QgsRenderContext &context ) const
1967 {
1968  // return width of the largest symbol
1969  double maxWidth = 0;
1970  for ( QgsSymbolLayer *layer : mLayers )
1971  {
1972  if ( layer->type() != QgsSymbol::Line )
1973  continue;
1974  const QgsLineSymbolLayer *lineLayer = static_cast<const QgsLineSymbolLayer *>( layer );
1975  const double layerWidth = lineLayer->width( context );
1976  maxWidth = std::max( maxWidth, layerWidth );
1977  }
1978  return maxWidth;
1979 }
1980 
1982 {
1983  const double symbolWidth = width();
1984 
1985  const auto constMLayers = mLayers;
1986  for ( QgsSymbolLayer *layer : constMLayers )
1987  {
1988  QgsLineSymbolLayer *lineLayer = dynamic_cast<QgsLineSymbolLayer *>( layer );
1989 
1990  if ( lineLayer )
1991  {
1992  if ( !property )
1993  {
1996  }
1997  else
1998  {
1999  if ( qgsDoubleNear( symbolWidth, 0.0 ) || qgsDoubleNear( lineLayer->width(), symbolWidth ) )
2000  {
2002  }
2003  else
2004  {
2005  lineLayer->setDataDefinedProperty( QgsSymbolLayer::PropertyStrokeWidth, scaleWholeSymbol( lineLayer->width() / symbolWidth, property ) );
2006  }
2007 
2008  if ( !qgsDoubleNear( lineLayer->offset(), 0.0 ) )
2009  {
2010  lineLayer->setDataDefinedProperty( QgsSymbolLayer::PropertyOffset, scaleWholeSymbol( lineLayer->offset() / symbolWidth, property ) );
2011  }
2012  }
2013  }
2014  }
2015 }
2016 
2018 {
2019  const double symbolWidth = width();
2020 
2021  QgsProperty symbolDD;
2022 
2023  // find the base of the "en masse" pattern
2024  for ( QgsSymbolLayerList::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
2025  {
2026  const QgsLineSymbolLayer *layer = dynamic_cast<const QgsLineSymbolLayer *>( *it );
2027  if ( layer && qgsDoubleNear( layer->width(), symbolWidth ) && layer->dataDefinedProperties().isActive( QgsSymbolLayer::PropertyStrokeWidth ) )
2028  {
2029  symbolDD = layer->dataDefinedProperties().property( QgsSymbolLayer::PropertyStrokeWidth );
2030  break;
2031  }
2032  }
2033 
2034  if ( !symbolDD )
2035  return QgsProperty();
2036 
2037  // check that all layers width expressions match the "en masse" pattern
2038  const auto constMLayers = mLayers;
2039  for ( QgsSymbolLayer *layer : constMLayers )
2040  {
2041  if ( layer->type() != QgsSymbol::Line )
2042  continue;
2043  const QgsLineSymbolLayer *lineLayer = static_cast<const QgsLineSymbolLayer *>( layer );
2044 
2047 
2048  if ( qgsDoubleNear( lineLayer->width(), symbolWidth ) )
2049  {
2050  if ( !layerWidthDD || layerWidthDD != symbolDD )
2051  return QgsProperty();
2052  }
2053  else
2054  {
2055  if ( qgsDoubleNear( symbolWidth, 0.0 ) )
2056  return QgsProperty();
2057 
2058  QgsProperty scaledDD( scaleWholeSymbol( lineLayer->width() / symbolWidth, symbolDD ) );
2059  if ( !layerWidthDD || layerWidthDD != scaledDD )
2060  return QgsProperty();
2061  }
2062 
2063  QgsProperty scaledOffsetDD( scaleWholeSymbol( lineLayer->offset() / symbolWidth, symbolDD ) );
2064  if ( layerOffsetDD && layerOffsetDD != scaledOffsetDD )
2065  return QgsProperty();
2066  }
2067 
2068  return symbolDD;
2069 }
2070 
2071 void QgsLineSymbol::renderPolyline( const QPolygonF &points, const QgsFeature *f, QgsRenderContext &context, int layerIdx, bool selected )
2072 {
2073  //save old painter
2074  QPainter *renderPainter = context.painter();
2075  QgsSymbolRenderContext symbolContext( context, QgsUnitTypes::RenderUnknownUnit, mOpacity, selected, mRenderHints, f );
2077  symbolContext.setGeometryPartCount( symbolRenderContext()->geometryPartCount() );
2078  symbolContext.setGeometryPartNum( symbolRenderContext()->geometryPartNum() );
2079 
2080  if ( layerIdx != -1 )
2081  {
2082  QgsSymbolLayer *symbolLayer = mLayers.value( layerIdx );
2084  {
2085  if ( symbolLayer->type() == QgsSymbol::Line )
2086  {
2087  QgsLineSymbolLayer *lineLayer = static_cast<QgsLineSymbolLayer *>( symbolLayer );
2088  renderPolylineUsingLayer( lineLayer, points, symbolContext );
2089  }
2090  else
2091  renderUsingLayer( symbolLayer, symbolContext );
2092  }
2093  return;
2094  }
2095 
2096  const auto constMLayers = mLayers;
2097  for ( QgsSymbolLayer *symbolLayer : constMLayers )
2098  {
2099  if ( context.renderingStopped() )
2100  break;
2101 
2102  if ( !symbolLayer->enabled() || !context.isSymbolLayerEnabled( symbolLayer ) )
2103  continue;
2104 
2105  if ( symbolLayer->type() == QgsSymbol::Line )
2106  {
2107  QgsLineSymbolLayer *lineLayer = static_cast<QgsLineSymbolLayer *>( symbolLayer );
2108  renderPolylineUsingLayer( lineLayer, points, symbolContext );
2109  }
2110  else
2111  {
2112  renderUsingLayer( symbolLayer, symbolContext );
2113  }
2114  }
2115 
2116  context.setPainter( renderPainter );
2117 }
2118 
2119 void QgsLineSymbol::renderPolylineUsingLayer( QgsLineSymbolLayer *layer, const QPolygonF &points, QgsSymbolRenderContext &context )
2120 {
2121  if ( layer->dataDefinedProperties().hasActiveProperties() && !layer->dataDefinedProperties().valueAsBool( QgsSymbolLayer::PropertyLayerEnabled, context.renderContext().expressionContext(), true ) )
2122  return;
2123 
2124  QgsPaintEffect *effect = layer->paintEffect();
2125  if ( effect && effect->enabled() )
2126  {
2127  QgsEffectPainter p( context.renderContext() );
2128  p->translate( points.boundingRect().topLeft() );
2129  p.setEffect( effect );
2130  layer->renderPolyline( points.translated( -points.boundingRect().topLeft() ), context );
2131  }
2132  else
2133  {
2134  layer->renderPolyline( points, context );
2135  }
2136 }
2137 
2138 
2140 {
2141  QgsLineSymbol *cloneSymbol = new QgsLineSymbol( cloneLayers() );
2142  cloneSymbol->setOpacity( mOpacity );
2144  cloneSymbol->setLayer( mLayer );
2147  cloneSymbol->setForceRHR( mForceRHR );
2148  return cloneSymbol;
2149 }
2150 
2152 // FILL
2153 
2155  : QgsSymbol( Fill, layers )
2156 {
2157  if ( mLayers.isEmpty() )
2158  mLayers.append( new QgsSimpleFillSymbolLayer() );
2159 }
2160 
2161 void QgsFillSymbol::renderPolygon( const QPolygonF &points, const QVector<QPolygonF> *rings, const QgsFeature *f, QgsRenderContext &context, int layerIdx, bool selected )
2162 {
2163  QgsSymbolRenderContext symbolContext( context, QgsUnitTypes::RenderUnknownUnit, mOpacity, selected, mRenderHints, f );
2165  symbolContext.setGeometryPartCount( symbolRenderContext()->geometryPartCount() );
2166  symbolContext.setGeometryPartNum( symbolRenderContext()->geometryPartNum() );
2167 
2168  if ( layerIdx != -1 )
2169  {
2170  QgsSymbolLayer *symbolLayer = mLayers.value( layerIdx );
2172  {
2173  if ( symbolLayer->type() == Fill || symbolLayer->type() == Line )
2174  renderPolygonUsingLayer( symbolLayer, points, rings, symbolContext );
2175  else
2176  renderUsingLayer( symbolLayer, symbolContext );
2177  }
2178  return;
2179  }
2180 
2181  const auto constMLayers = mLayers;
2182  for ( QgsSymbolLayer *symbolLayer : constMLayers )
2183  {
2184  if ( context.renderingStopped() )
2185  break;
2186 
2187  if ( !symbolLayer->enabled() || !context.isSymbolLayerEnabled( symbolLayer ) )
2188  continue;
2189 
2190  if ( symbolLayer->type() == Fill || symbolLayer->type() == Line )
2191  renderPolygonUsingLayer( symbolLayer, points, rings, symbolContext );
2192  else
2193  renderUsingLayer( symbolLayer, symbolContext );
2194  }
2195 }
2196 
2197 void QgsFillSymbol::renderPolygonUsingLayer( QgsSymbolLayer *layer, const QPolygonF &points, const QVector<QPolygonF> *rings, QgsSymbolRenderContext &context )
2198 {
2199  if ( layer->dataDefinedProperties().hasActiveProperties() && !layer->dataDefinedProperties().valueAsBool( QgsSymbolLayer::PropertyLayerEnabled, context.renderContext().expressionContext(), true ) )
2200  return;
2201 
2202  QgsSymbol::SymbolType layertype = layer->type();
2203 
2204  QgsPaintEffect *effect = layer->paintEffect();
2205  if ( effect && effect->enabled() )
2206  {
2207  QRectF bounds = polygonBounds( points, rings );
2208  QVector<QPolygonF> *translatedRings = translateRings( rings, -bounds.left(), -bounds.top() );
2209 
2210  QgsEffectPainter p( context.renderContext() );
2211  p->translate( bounds.topLeft() );
2212  p.setEffect( effect );
2213  if ( layertype == QgsSymbol::Fill )
2214  {
2215  ( static_cast<QgsFillSymbolLayer *>( layer ) )->renderPolygon( points.translated( -bounds.topLeft() ), translatedRings, context );
2216  }
2217  else if ( layertype == QgsSymbol::Line )
2218  {
2219  ( static_cast<QgsLineSymbolLayer *>( layer ) )->renderPolygonStroke( points.translated( -bounds.topLeft() ), translatedRings, context );
2220  }
2221  delete translatedRings;
2222  }
2223  else
2224  {
2225  if ( layertype == QgsSymbol::Fill )
2226  {
2227  ( static_cast<QgsFillSymbolLayer *>( layer ) )->renderPolygon( points, rings, context );
2228  }
2229  else if ( layertype == QgsSymbol::Line )
2230  {
2231  ( static_cast<QgsLineSymbolLayer *>( layer ) )->renderPolygonStroke( points, rings, context );
2232  }
2233  }
2234 }
2235 
2236 QRectF QgsFillSymbol::polygonBounds( const QPolygonF &points, const QVector<QPolygonF> *rings ) const
2237 {
2238  QRectF bounds = points.boundingRect();
2239  if ( rings )
2240  {
2241  for ( auto it = rings->constBegin(); it != rings->constEnd(); ++it )
2242  {
2243  bounds = bounds.united( ( *it ).boundingRect() );
2244  }
2245  }
2246  return bounds;
2247 }
2248 
2249 QVector<QPolygonF> *QgsFillSymbol::translateRings( const QVector<QPolygonF> *rings, double dx, double dy ) const
2250 {
2251  if ( !rings )
2252  return nullptr;
2253 
2254  QVector<QPolygonF> *translatedRings = new QVector<QPolygonF>;
2255  translatedRings->reserve( rings->size() );
2256  for ( auto it = rings->constBegin(); it != rings->constEnd(); ++it )
2257  {
2258  translatedRings->append( ( *it ).translated( dx, dy ) );
2259  }
2260  return translatedRings;
2261 }
2262 
2264 {
2265  QgsFillSymbol *cloneSymbol = new QgsFillSymbol( cloneLayers() );
2266  cloneSymbol->setOpacity( mOpacity );
2268  cloneSymbol->setLayer( mLayer );
2271  cloneSymbol->setForceRHR( mForceRHR );
2272  return cloneSymbol;
2273 }
2274 
2276 {
2277  const auto constMLayers = mLayers;
2278  for ( QgsSymbolLayer *layer : constMLayers )
2279  {
2280  if ( layer->type() != QgsSymbol::Fill )
2281  continue;
2282 
2283  QgsFillSymbolLayer *fillLayer = static_cast<QgsFillSymbolLayer *>( layer );
2284 
2285  if ( fillLayer )
2286  fillLayer->setAngle( angle );
2287  }
2288 }
2289 
2290 
QgsCurve
Abstract base class for curved geometry type.
Definition: qgscurve.h:35
qgspolygon.h
QgsLineSymbolLayer
Definition: qgssymbollayer.h:894
QgsSymbolRenderContext::setOriginalValueVariable
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for data defined symbology.
Definition: qgssymbol.cpp:1370
QgsSymbol::setLayer
Q_DECL_DEPRECATED void setLayer(const QgsVectorLayer *layer)
Definition: qgssymbol.cpp:763
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:369
QgsSymbol::cloneLayers
QgsSymbolLayerList cloneLayers() const
Retrieve a cloned list of all layers that make up this symbol.
Definition: qgssymbol.cpp:703
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:155
QgsMarkerSymbol::setAngle
void setAngle(double symbolAngle)
Sets the angle for the whole symbol.
Definition: qgssymbol.cpp:1460
QgsSymbolLayer::enabled
bool enabled() const
Returns true if symbol layer is enabled and will be drawn.
Definition: qgssymbollayer.h:212
QgsSymbol::mLayer
const Q_DECL_DEPRECATED QgsVectorLayer * mLayer
Definition: qgssymbol.h:627
QgsFillSymbol::QgsFillSymbol
QgsFillSymbol(const QgsSymbolLayerList &layers=QgsSymbolLayerList())
Constructor for QgsFillSymbol, with the specified list of initial symbol layers.
Definition: qgssymbol.cpp:2154
qgsexpressioncontextutils.h
QgsExpressionContext::appendScopes
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
Definition: qgsexpressioncontext.cpp:495
QgsMarkerSymbolLayer::setSizeUnit
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the symbol's size.
Definition: qgssymbollayer.h:664
QgsSymbol::color
QColor color() const
Returns the symbol's color.
Definition: qgssymbol.cpp:495
QgsSimpleFillSymbolLayer::create
static QgsSymbolLayer * create(const QgsStringMap &properties=QgsStringMap())
Creates a new QgsSimpleFillSymbolLayer using the specified properties map containing symbol propertie...
Definition: qgsfillsymbollayer.cpp:150
QgsRenderContext::testFlag
bool testFlag(Flag flag) const
Check whether a particular flag is enabled.
Definition: qgsrendercontext.cpp:165
QgsSymbol::mRenderHints
RenderHints mRenderHints
Definition: qgssymbol.h:623
QgsLegendPatchShape::toQPolygonF
QList< QList< QPolygonF > > toQPolygonF(QgsSymbol::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:84
QgsSymbolLayerUtils::encodeColor
static QString encodeColor(const QColor &color)
Definition: qgssymbollayerutils.cpp:52
QgsClipper::clippedLine
static QPolygonF clippedLine(const QgsCurve &curve, const QgsRectangle &clipExtent)
Takes a linestring and clips it to clipExtent.
Definition: qgsclipper.cpp:41
QgsRenderContext::setIsGuiPreview
void setIsGuiPreview(bool preview)
Sets GUI preview mode.
Definition: qgsrendercontext.h:750
QgsMarkerSymbol::setDataDefinedAngle
void setDataDefinedAngle(const QgsProperty &property)
Set data defined angle for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1497
QgsRenderContext::convertToPainterUnits
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels).
Definition: qgsrendercontext.cpp:287
QgsAbstractGeometry::wkbType
QgsWkbTypes::Type wkbType() const
Returns the WKB type of the geometry.
Definition: qgsabstractgeometry.h:189
QgsSymbolLayer::startFeatureRender
virtual void startFeatureRender(const QgsFeature &feature, QgsRenderContext &context)
Called before the layer will be rendered for a particular feature.
Definition: qgssymbollayer.cpp:117
QgsRenderContext::mapToPixel
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
Definition: qgsrendercontext.h:309
QgsWkbTypes::Triangle
@ Triangle
Definition: qgswkbtypes.h:74
QgsMarkerSymbolLayer::size
double size() const
Returns the symbol size.
Definition: qgssymbollayer.h:655
QgsSymbolLayer::dataDefinedProperties
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
Definition: qgssymbollayer.h:480
QgsProperty
A store for object properties.
Definition: qgsproperty.h:231
QgsUnitTypes::RenderUnit
RenderUnit
Rendering size units.
Definition: qgsunittypes.h:166
QgsWkbTypes::Point
@ Point
Definition: qgswkbtypes.h:71
QgsRenderContext::expressionContext
QgsExpressionContext & expressionContext()
Gets the expression context.
Definition: qgsrendercontext.h:580
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:301
QgsLineSymbolLayer::width
virtual double width() const
Returns the estimated width for the line symbol layer.
Definition: qgssymbollayer.h:959
QgsEffectPainter
A class to manager painter saving and restoring required for effect drawing.
Definition: qgspainteffect.h:396
QgsWkbTypes::MultiPolygon
@ MultiPolygon
Definition: qgswkbtypes.h:77
QgsMarkerSymbol::setSizeUnit
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the size units for the whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1629
QgsPoint
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
QgsMarkerSymbol::size
double size() const
Returns the estimated size for the whole symbol, which is the maximum size of all marker symbol layer...
Definition: qgssymbol.cpp:1597
QgsGeometryCollection::numGeometries
int numGeometries() const
Returns the number of geometries within the collection.
Definition: qgsgeometrycollection.h:51
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QgsSimpleLineSymbolLayer::create
static QgsSymbolLayer * create(const QgsStringMap &properties=QgsStringMap())
Creates a new QgsSimpleLineSymbolLayer, using the settings serialized in the properties map (correspo...
Definition: qgslinesymbollayer.cpp:81
QgsSymbol::renderUsingLayer
void renderUsingLayer(QgsSymbolLayer *layer, QgsSymbolRenderContext &context)
Renders a context using a particular symbol layer without passing in a geometry.
Definition: qgssymbol.cpp:717
QgsMarkerSymbol::dataDefinedSize
QgsProperty dataDefinedSize() const
Returns data defined size for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1731
QgsSymbol::takeSymbolLayer
QgsSymbolLayer * takeSymbolLayer(int index)
Removes a symbol layer from the list and returns a pointer to it.
Definition: qgssymbol.cpp:410
QgsLineSymbol::width
double width() const
Returns the estimated width for the whole symbol, which is the maximum width of all marker symbol lay...
Definition: qgssymbol.cpp:1946
QgsRenderContext::setFlag
void setFlag(Flag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
Definition: qgsrendercontext.cpp:152
QgsLineSymbol::clone
QgsLineSymbol * clone() const override
Returns a deep copy of this symbol.
Definition: qgssymbol.cpp:2139
QgsLineSymbolLayer::setWidth
virtual void setWidth(double width)
Sets the width of the line symbol layer.
Definition: qgssymbollayer.h:948
QgsMarkerSymbol::createSimple
static QgsMarkerSymbol * createSimple(const QgsStringMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
Definition: qgssymbol.cpp:1418
QgsRenderContext::setPainter
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
Definition: qgsrendercontext.h:475
QgsRectangle::xMaximum
double xMaximum() const
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:162
QgsSymbol::layer
const Q_DECL_DEPRECATED QgsVectorLayer * layer() const
Definition: qgssymbol.cpp:770
QgsExpressionContext::setOriginalValueVariable
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for the context.
Definition: qgsexpressioncontext.cpp:566
QgsWkbTypes::LineString
@ LineString
Definition: qgswkbtypes.h:72
QgsMarkerSymbolLayer::setAngle
void setAngle(double angle)
Sets the rotation angle for the marker.
Definition: qgssymbollayer.h:621
QgsFields
Definition: qgsfields.h:44
QgsSymbolRenderContext::setSelected
void setSelected(bool selected)
Sets whether symbols should be rendered using the selected symbol coloring and style.
Definition: qgssymbol.h:770
QgsSymbolRenderContext::setGeometryPartNum
void setGeometryPartNum(int num)
Sets the part number of current geometry.
Definition: qgssymbol.h:838
QgsMarkerSymbolLayer::scaleMethod
QgsSymbol::ScaleMethod scaleMethod() const
Returns the method to use for scaling the marker's size.
Definition: qgssymbollayer.h:702
qgsfeature.h
QgsProperty::asExpression
QString asExpression() const
Returns an expression string representing the state of the property, or an empty string if the proper...
Definition: qgsproperty.cpp:332
qgsmultipoint.h
qgsmarkersymbollayer.h
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:71
QgsVectorSimplifyMethod::simplifyAlgorithm
SimplifyAlgorithm simplifyAlgorithm() const
Gets the local simplification algorithm of the vector layer managed.
Definition: qgsvectorsimplifymethod.h:79
QgsCurvePolygon::exteriorRing
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
Definition: qgscurvepolygon.h:86
qgsrenderedfeaturehandlerinterface.h
QgsRenderContext
Definition: qgsrendercontext.h:57
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:458
QgsSymbol::hasDataDefinedProperties
bool hasDataDefinedProperties() const
Returns whether the symbol utilizes any data defined properties.
Definition: qgssymbol.cpp:752
QgsApplication::colorSchemeRegistry
static QgsColorSchemeRegistry * colorSchemeRegistry()
Returns the application's color scheme registry, used for managing color schemes.
Definition: qgsapplication.cpp:2089
QgsUnitTypes::RenderMillimeters
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:168
QgsMarkerSymbol::setDataDefinedSize
void setDataDefinedSize(const QgsProperty &property)
Set data defined size for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1694
QgsExpressionContextUtils::globalProjectLayerScopes
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Definition: qgsexpressioncontextutils.cpp:306
QgsMarkerSymbolLayer
Abstract base class for marker symbol layers.
Definition: qgssymbollayer.h:575
QgsWkbTypes::MultiCurve
@ MultiCurve
Definition: qgswkbtypes.h:82
QgsSymbol::mapUnitScale
QgsMapUnitScale mapUnitScale() const
Returns the map unit scale for the symbol.
Definition: qgssymbol.cpp:259
QgsSymbol::ScaleMethod
ScaleMethod
Scale method.
Definition: qgssymbol.h:96
QgsExpressionContext::EXPR_GEOMETRY_PART_NUM
static const QString EXPR_GEOMETRY_PART_NUM
Inbuilt variable name for geometry part number variable.
Definition: qgsexpressioncontext.h:729
QgsSymbolRenderContext::~QgsSymbolRenderContext
~QgsSymbolRenderContext()
QgsProject::readEntry
QString readEntry(const QString &scope, const QString &key, const QString &def=QString(), bool *ok=nullptr) const
Definition: qgsproject.cpp:2448
FALLTHROUGH
#define FALLTHROUGH
Definition: qgis.h:783
QgsSymbol
Definition: qgssymbol.h:63
QgsProperty::fromExpression
static QgsProperty fromExpression(const QString &expression, bool isActive=true)
Returns a new ExpressionBasedProperty created from the specified expression.
Definition: qgsproperty.cpp:212
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
QgsMarkerSymbol::angle
double angle() const
Returns the marker angle for the whole symbol.
Definition: qgssymbol.cpp:1473
QgsProject::readBoolEntry
bool readBoolEntry(const QString &scope, const QString &key, bool def=false, bool *ok=nullptr) const
Definition: qgsproject.cpp:2519
QgsSymbol::symbolLayer
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
Definition: qgssymbol.cpp:366
QgsSymbol::insertSymbolLayer
bool insertSymbolLayer(int index, QgsSymbolLayer *layer)
Inserts a symbol layer to specified index.
Definition: qgssymbol.cpp:376
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:876
QgsSimpleMarkerSymbolLayer::create
static QgsSymbolLayer * create(const QgsStringMap &properties=QgsStringMap())
Creates a new QgsSimpleMarkerSymbolLayer.
Definition: qgsmarkersymbollayer.cpp:715
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:290
QgsSymbol::outputUnit
QgsUnitTypes::RenderUnit outputUnit() const
Returns the units to use for sizes and widths within the symbol.
Definition: qgssymbol.cpp:238
QgsSymbol::QgsSymbol
QgsSymbol(SymbolType type, const QgsSymbolLayerList &layers)
Definition: qgssymbol.cpp:83
QgsLineSymbol::setWidth
void setWidth(double width)
Sets the width for the whole line symbol.
Definition: qgssymbol.cpp:1919
QgsSymbolRenderContext::patchShape
const QgsLegendPatchShape * patchShape() const
Returns the symbol patch shape, to use if rendering symbol preview icons.
Definition: qgssymbol.cpp:1406
QgsLineSymbolLayer::setOffset
void setOffset(double offset)
Sets the line's offset.
Definition: qgssymbollayer.h:993
QgsRectangle
Definition: qgsrectangle.h:41
QgsCoordinateTransform::transformPolygon
void transformPolygon(QPolygonF &polygon, TransformDirection direction=ForwardTransform) const SIP_THROW(QgsCsException)
Transforms a polygon to the destination coordinate system.
Definition: qgscoordinatetransform.cpp:370
QgsWkbTypes::PolygonGeometry
@ PolygonGeometry
Definition: qgswkbtypes.h:143
QgsCurvePolygon::interiorRing
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
Definition: qgscurvepolygon.h:99
QgsLegendPatchShape
Definition: qgslegendpatchshape.h:30
qgsDoubleToString
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:275
QgsRenderedFeatureHandlerInterface
Definition: qgsrenderedfeaturehandlerinterface.h:46
QgsGeometry::fromRect
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
Definition: qgsgeometry.cpp:229
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:217
QgsPropertyCollection::property
QgsProperty property(int key) const override
Returns a matching property from the collection, if one exists.
Definition: qgspropertycollection.cpp:204
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:584
QgsMarkerSymbol::clone
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
Definition: qgssymbol.cpp:1896
QgsSymbolRenderContext::setPatchShape
void setPatchShape(const QgsLegendPatchShape &shape)
Sets the symbol patch shape, to use if rendering symbol preview icons.
Definition: qgssymbol.cpp:1411
rotateWholeSymbol
QgsProperty rotateWholeSymbol(double additionalRotation, const QgsProperty &property)
Definition: qgssymbol.cpp:56
QgsMarkerSymbolLayer::sizeUnit
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the units for the symbol's size.
Definition: qgssymbollayer.h:672
QgsStyle::defaultStyle
static QgsStyle * defaultStyle()
Returns default application-wide style.
Definition: qgsstyle.cpp:111
qgsapplication.h
QgsSymbolRenderContext
Definition: qgssymbol.h:681
QgsSymbolRenderContext::expressionContextScope
QgsExpressionContextScope * expressionContextScope()
This scope is always available when a symbol of this type is being rendered.
Definition: qgssymbol.cpp:1396
QgsSymbol::setMapUnitScale
void setMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the symbol.
Definition: qgssymbol.cpp:292
QgsMarkerSymbol::scaleMethod
ScaleMethod scaleMethod()
Definition: qgssymbol.cpp:1799
QgsSymbol::setOpacity
void setOpacity(qreal opacity)
Sets the opacity for the symbol.
Definition: qgssymbol.h:452
Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:752
QgsRenderContext::renderingStopped
bool renderingStopped() const
Returns true if the rendering operation has been stopped and any ongoing rendering should be canceled...
Definition: qgsrendercontext.h:325
QgsSymbol::setClipFeaturesToExtent
void setClipFeaturesToExtent(bool clipFeaturesToExtent)
Sets whether features drawn by the symbol should be clipped to the render context's extent.
Definition: qgssymbol.h:475
QgsRenderContext::coordinateTransform
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
Definition: qgsrendercontext.h:229
QgsPoint::y
double y
Definition: qgspoint.h:59
QgsSymbol::opacity
qreal opacity() const
Returns the opacity for the symbol.
Definition: qgssymbol.h:445
QgsWkbTypes::MultiLineString
@ MultiLineString
Definition: qgswkbtypes.h:76
QgsGeometryCollection
Geometry collection.
Definition: qgsgeometrycollection.h:35
QgsSymbolLayer::PropertyOffset
@ PropertyOffset
Symbol offset.
Definition: qgssymbollayer.h:139
QgsSymbol::bigSymbolPreviewImage
QImage bigSymbolPreviewImage(QgsExpressionContext *expressionContext=nullptr)
Returns a large (roughly 100x100 pixel) preview image for the symbol.
Definition: qgssymbol.cpp:618
QgsCsException
Definition: qgsexception.h:65
QgsSymbolLayer
Definition: qgssymbollayer.h:52
QgsRenderContext::forceVectorOutput
bool forceVectorOutput() const
Returns true if rendering operations should use vector operations instead of any faster raster shortc...
Definition: qgsrendercontext.cpp:215
QgsSymbol::changeSymbolLayer
bool changeSymbolLayer(int index, QgsSymbolLayer *layer)
Deletes the current layer at the specified index and replaces it with layer.
Definition: qgssymbol.cpp:419
QgsSymbol::setOutputUnit
void setOutputUnit(QgsUnitTypes::RenderUnit unit)
Sets the units to use for sizes and widths within the symbol.
Definition: qgssymbol.cpp:283
QgsSymbol::appendSymbolLayer
bool appendSymbolLayer(QgsSymbolLayer *layer)
Appends a symbol layer at the end of the current symbol layer list.
Definition: qgssymbol.cpp:389
QgsSymbol::stopRender
void stopRender(QgsRenderContext &context)
Ends the rendering process.
Definition: qgssymbol.cpp:460
QgsFillSymbol::setAngle
void setAngle(double angle)
Definition: qgssymbol.cpp:2275
QgsClipper::trimPolygon
static void trimPolygon(QPolygonF &pts, const QgsRectangle &clipRect)
Definition: qgsclipper.h:202
QgsSymbol::mType
SymbolType mType
Definition: qgssymbol.h:617
QgsMapToPixelSimplifier::SimplifyAlgorithm
SimplifyAlgorithm
Types of simplification algorithms that can be used.
Definition: qgsmaptopixelgeometrysimplifier.h:42
QgsSymbol::mLayers
QgsSymbolLayerList mLayers
Definition: qgssymbol.h:618
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:217
QgsCurve::asQPolygonF
virtual QPolygonF asQPolygonF() const
Returns a QPolygonF representing the points.
Definition: qgscurve.cpp:223
QgsSymbol::toSld
void toSld(QDomDocument &doc, QDomElement &element, QgsStringMap props) const
Converts the symbol to a SLD representation.
Definition: qgssymbol.cpp:690
QgsRectangle::contains
bool contains(const QgsRectangle &rect) const
Returns true when rectangle contains other rectangle.
Definition: qgsrectangle.h:342
QgsMarkerSymbol
Definition: qgssymbol.h:917
QgsSymbol::renderFeature
void renderFeature(const QgsFeature &feature, QgsRenderContext &context, int layer=-1, bool selected=false, bool drawVertexMarker=false, int currentVertexMarkerType=0, double currentVertexMarkerSize=0.0) SIP_THROW(QgsCsException)
Render a feature.
Definition: qgssymbol.cpp:819
QgsSymbolLayer::stopFeatureRender
virtual void stopFeatureRender(const QgsFeature &feature, QgsRenderContext &context)
Called after the layer has been rendered for a particular feature.
Definition: qgssymbollayer.cpp:122
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:315
QgsMarkerSymbol::setLineAngle
void setLineAngle(double lineAngle)
Sets the line angle modification for the symbol's angle.
Definition: qgssymbol.cpp:1485
QgsWkbTypes::GeometryCollection
@ GeometryCollection
Definition: qgswkbtypes.h:78
QgsCurve::Clockwise
@ Clockwise
Clockwise orientation.
Definition: qgscurve.h:238
QgsSimpleLineSymbolLayer
Definition: qgslinesymbollayer.h:39
QgsSimpleMarkerSymbolLayer
Simple marker symbol layer, consisting of a rendered shape with solid fill color and an stroke.
Definition: qgsmarkersymbollayer.h:198
QgsSymbol::dump
QString dump() const
Returns a string dump of the symbol's properties.
Definition: qgssymbol.cpp:664
QgsSymbolLayer::PropertySize
@ PropertySize
Symbol size.
Definition: qgssymbollayer.h:132
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:676
QgsSymbolRenderContext::setGeometryPartCount
void setGeometryPartCount(int count)
Sets the part count of current geometry.
Definition: qgssymbol.h:826
QgsGeometryGeneratorSymbolLayer
Definition: qgsgeometrygeneratorsymbollayer.h:26
QgsMarkerSymbol::setScaleMethod
void setScaleMethod(QgsSymbol::ScaleMethod scaleMethod)
Definition: qgssymbol.cpp:1787
QgsCurve::CounterClockwise
@ CounterClockwise
Counter-clockwise orientation.
Definition: qgscurve.h:239
qgsrendercontext.h
QgsLineSymbol
Definition: qgssymbol.h:1117
QgsRenderContext::segmentationTolerance
double segmentationTolerance() const
Gets the segmentation tolerance applied when rendering curved geometries.
Definition: qgsrendercontext.h:624
QgsRenderContext::segmentationToleranceType
QgsAbstractGeometry::SegmentationToleranceType segmentationToleranceType() const
Gets segmentation tolerance type (maximum angle or maximum difference between curve and approximation...
Definition: qgsrendercontext.h:638
QgsRenderContext::DrawSymbolBounds
@ DrawSymbolBounds
Draw bounds of symbols (for debugging/testing)
Definition: qgsrendercontext.h:76
QgsLineSymbol::dataDefinedWidth
QgsProperty dataDefinedWidth() const
Returns data defined width for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:2017
qgssymbollayer.h
QgsRenderContext::RenderMapTile
@ RenderMapTile
Draw map such that there are no problems between adjacent tiles.
Definition: qgsrendercontext.h:77
QgsSymbolRenderContext::outputLineWidth
Q_DECL_DEPRECATED double outputLineWidth(double width) const
Definition: qgssymbol.cpp:1375
QgsGeometry::isNull
bool isNull
Definition: qgsgeometry.h:125
qgslegendpatchshape.h
QgsMarkerSymbolLayer::setOffset
void setOffset(QPointF offset)
Sets the marker's offset, which is the horizontal and vertical displacement which the rendered marker...
Definition: qgssymbollayer.h:712
QgsProject::readDoubleEntry
double readDoubleEntry(const QString &scope, const QString &key, double def=0, bool *ok=nullptr) const
Definition: qgsproject.cpp:2499
QgsSymbol::Fill
@ Fill
Fill symbol.
Definition: qgssymbol.h:89
QgsMapUnitScale
Struct for storing maximum and minimum scales for measurements in map units.
Definition: qgsmapunitscale.h:37
QgsAbstractGeometry::hasCurvedSegments
virtual bool hasCurvedSegments() const
Returns true if the geometry contains curved segments.
Definition: qgsabstractgeometry.cpp:305
QgsGeometry::constGet
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Definition: qgsgeometry.cpp:128
QgsSymbol::startRender
void startRender(QgsRenderContext &context, const QgsFields &fields=QgsFields())
Begins the rendering process for the symbol.
Definition: qgssymbol.cpp:435
QgsSymbolLayer::paintEffect
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the layer.
Definition: qgssymbollayer.cpp:185
QgsVectorSimplifyMethod::tolerance
double tolerance() const
Gets the tolerance of simplification in map units. Represents the maximum distance in map units betwe...
Definition: qgsvectorsimplifymethod.h:84
qgseffectstack.h
qgsfillsymbollayer.h
QgsSymbol::renderVertexMarker
void renderVertexMarker(QPointF pt, QgsRenderContext &context, int currentVertexMarkerType, double currentVertexMarkerSize)
Render editing vertex marker at specified point.
Definition: qgssymbol.cpp:1297
QgsFillSymbol::renderPolygon
void renderPolygon(const QPolygonF &points, const QVector< QPolygonF > *rings, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
Renders the symbol using the given render context.
Definition: qgssymbol.cpp:2161
QgsSymbolLayer::PropertyStrokeWidth
@ PropertyStrokeWidth
Stroke width.
Definition: qgssymbollayer.h:137
QgsSymbol::symbolRenderContext
QgsSymbolRenderContext * symbolRenderContext()
Returns the symbol render context.
Definition: qgssymbol.cpp:1292
QgsVectorSimplifyMethod::forceLocalOptimization
bool forceLocalOptimization() const
Gets where the simplification executes, after fetch the geometries from provider, or when supported,...
Definition: qgsvectorsimplifymethod.h:94
QgsMultiPoint
Multi point geometry collection.
Definition: qgsmultipoint.h:29
QgsSymbol::setForceRHR
void setForceRHR(bool force)
Sets whether polygon features drawn by the symbol should be reoriented to follow the standard right-h...
Definition: qgssymbol.h:497
QgsMarkerSymbolLayer::setLineAngle
void setLineAngle(double lineAngle)
Sets the line angle modification for the symbol's angle.
Definition: qgssymbollayer.h:638
QgsAbstractGeometry
Abstract base class for all geometries.
Definition: qgsabstractgeometry.h:71
QgsRectangle::yMaximum
double yMaximum() const
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:172
QgsExpressionContextScope
Single scope for storing variables and functions for use within a QgsExpressionContext....
Definition: qgsexpressioncontext.h:111
QgsRenderContext::vectorSimplifyMethod
const QgsVectorSimplifyMethod & vectorSimplifyMethod() const
Returns the simplification settings to use when rendering vector layers.
Definition: qgsrendercontext.h:549
qgsclipper.h
QgsAbstractGeometry::segmentize
virtual QgsAbstractGeometry * segmentize(double tolerance=M_PI/180., SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a version of the geometry without curves.
Definition: qgsabstractgeometry.cpp:310
qgsstyle.h
QgsSymbol::~QgsSymbol
virtual ~QgsSymbol()
Definition: qgssymbol.cpp:232
QgsMarkerSymbol::bounds
QRectF bounds(QPointF point, QgsRenderContext &context, const QgsFeature &feature=QgsFeature()) const
Returns the approximate bounding box of the marker symbol, which includes the bounding box of all sym...
Definition: qgssymbol.cpp:1876
QgsMapToPixelSimplifier
Definition: qgsmaptopixelgeometrysimplifier.h:38
QgsSymbolLayer::PropertyLayerEnabled
@ PropertyLayerEnabled
Whether symbol layer is enabled.
Definition: qgssymbollayer.h:176
QgsExpressionContext::appendScope
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
Definition: qgsexpressioncontext.cpp:490
qgsvectorlayer.h
QgsRenderContext::setForceVectorOutput
void setForceVectorOutput(bool force)
Sets whether rendering operations should use vector operations instead of any faster raster shortcuts...
Definition: qgsrendercontext.cpp:250
QgsExpressionContext::EXPR_GEOMETRY_PART_COUNT
static const QString EXPR_GEOMETRY_PART_COUNT
Inbuilt variable name for geometry part count variable.
Definition: qgsexpressioncontext.h:727
QgsSymbol::mOpacity
qreal mOpacity
Symbol opacity (in the range 0 - 1)
Definition: qgssymbol.h:621
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: qgssymbol.h:796
QgsMapToPixel::transformInPlace
void transformInPlace(double &x, double &y) const
Transform device coordinates to map coordinates.
Definition: qgsmaptopixel.cpp:233
QgsWkbTypes::LineGeometry
@ LineGeometry
Definition: qgswkbtypes.h:142
QgsCurvePolygon::numInteriorRings
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
Definition: qgscurvepolygon.h:76
QgsStringMap
QMap< QString, QString > QgsStringMap
Definition: qgis.h:714
QgsWkbTypes::PointGeometry
@ PointGeometry
Definition: qgswkbtypes.h:141
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:553
QgsSymbolRenderContext::outputPixelSize
Q_DECL_DEPRECATED double outputPixelSize(double size) const
Definition: qgssymbol.cpp:1380
QgsStyle::defaultPatchAsQPolygonF
QList< QList< QPolygonF > > defaultPatchAsQPolygonF(QgsSymbol::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:1072
QgsGeometryCollection::geometryN
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
Definition: qgsgeometrycollection.h:79
qgsgeometry.h
QgsLineSymbol::setDataDefinedWidth
void setDataDefinedWidth(const QgsProperty &property)
Set data defined width for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1981
QgsWkbTypes::MultiSurface
@ MultiSurface
Definition: qgswkbtypes.h:83
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:458
scaleWholeSymbol
QgsProperty scaleWholeSymbol(double scaleFactor, const QgsProperty &property)
Definition: qgssymbol.cpp:63
QgsWkbTypes::GeometryType
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:139
QgsSymbol::clipFeaturesToExtent
bool clipFeaturesToExtent() const
Returns whether features drawn by the symbol will be clipped to the render context's extent.
Definition: qgssymbol.h:486
c
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
Definition: porting_processing.dox:1
QgsGeometry
Definition: qgsgeometry.h:122
QgsSymbol::setColor
void setColor(const QColor &color)
Sets the color for the symbol.
Definition: qgssymbol.cpp:485
QgsGeometryGeneratorSymbolLayer::render
virtual void render(QgsSymbolRenderContext &context)
Will render this symbol layer using the context.
Definition: qgsgeometrygeneratorsymbollayer.cpp:204
QgsMapToPixel
Definition: qgsmaptopixel.h:37
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:506
QgsVectorLayer
Definition: qgsvectorlayer.h:385
QgsMarkerSymbol::dataDefinedAngle
QgsProperty dataDefinedAngle() const
Returns data defined angle for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1526
QgsSymbolLayerList
QList< QgsSymbolLayer * > QgsSymbolLayerList
Definition: qgssymbol.h:53
QgsLineSymbol::createSimple
static QgsLineSymbol * createSimple(const QgsStringMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties.
Definition: qgssymbol.cpp:1429
QgsRenderContext::fromQPainter
static QgsRenderContext fromQPainter(QPainter *painter)
Creates a default render context given a pixel based QPainter destination.
Definition: qgsrendercontext.cpp:111
QgsSymbolRenderContext::QgsSymbolRenderContext
QgsSymbolRenderContext(QgsRenderContext &c, QgsUnitTypes::RenderUnit u, qreal opacity=1.0, bool selected=false, QgsSymbol::RenderHints renderHints=nullptr, const QgsFeature *f=nullptr, const QgsFields &fields=QgsFields(), const QgsMapUnitScale &mapUnitScale=QgsMapUnitScale())
Constructor for QgsSymbolRenderContext.
Definition: qgssymbol.cpp:1354
QgsWkbTypes::displayString
static QString displayString(Type type)
Returns a display string type for a WKB type, e.g., the geometry name used in WKT geometry representa...
Definition: qgswkbtypes.cpp:145
QgsWkbTypes::Polygon
@ Polygon
Definition: qgswkbtypes.h:73
QgsFillSymbolLayer
Definition: qgssymbollayer.h:1092
DEFAULT_SCALE_METHOD
#define DEFAULT_SCALE_METHOD
Definition: qgssymbollayer.h:19
QgsWkbTypes::MultiPoint
@ MultiPoint
Definition: qgswkbtypes.h:75
QgsMapToPixelSimplifier::simplify
QgsGeometry simplify(const QgsGeometry &geometry) const override
Returns a simplified version the specified geometry.
Definition: qgsmaptopixelgeometrysimplifier.cpp:381
QgsSymbol::usedAttributes
QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns a list of attributes required to render this feature.
Definition: qgssymbol.cpp:738
QgsSymbol::deleteSymbolLayer
bool deleteSymbolLayer(int index)
Removes and deletes the symbol layer at the specified index.
Definition: qgssymbol.cpp:399
QgsVertexId
Utility class for identifying a unique vertex within a geometry.
Definition: qgsabstractgeometry.h:1033
qgsmaptopixelgeometrysimplifier.h
QgsPaintEffect
Base class for visual effects which can be applied to QPicture drawings.
Definition: qgspainteffect.h:53
QgsSimpleFillSymbolLayer
Definition: qgsfillsymbollayer.h:39
QgsFillSymbol::clone
QgsFillSymbol * clone() const override
Returns a deep copy of this symbol.
Definition: qgssymbol.cpp:2263
QgsRectangle::height
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:209
QgsSymbolLayer::PropertyAngle
@ PropertyAngle
Symbol angle.
Definition: qgssymbollayer.h:133
QgsFillSymbol
Definition: qgssymbol.h:1212
qgscolorschemeregistry.h
QgsLineSymbol::renderPolyline
void renderPolyline(const QPolygonF &points, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
Renders the symbol along the line joining points, using the given render context.
Definition: qgssymbol.cpp:2071
qgsproperty.h
QgsSymbol::Line
@ Line
Line symbol.
Definition: qgssymbol.h:88
QgsLineSymbol::QgsLineSymbol
QgsLineSymbol(const QgsSymbolLayerList &layers=QgsSymbolLayerList())
Constructor for QgsLineSymbol, with the specified list of initial symbol layers.
Definition: qgssymbol.cpp:1912
QgsUnitTypes::RenderUnknownUnit
@ RenderUnknownUnit
Mixed or unknown units.
Definition: qgsunittypes.h:174
QgsSymbolLayerUtils::VertexMarkerType
VertexMarkerType
Editing vertex markers.
Definition: qgssymbollayerutils.h:59
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:144
QgsRectangle::yMinimum
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:177
QgsWkbTypes::isCurvedType
static bool isCurvedType(Type type)
Returns true if the WKB type is a curved type or can contain curved geometries.
Definition: qgswkbtypes.h:880
QgsSymbol::type
SymbolType type() const
Returns the symbol's type.
Definition: qgssymbol.h:122
QgsSymbol::Marker
@ Marker
Marker symbol.
Definition: qgssymbol.h:87
QgsSymbolRenderContext::setExpressionContextScope
void setExpressionContextScope(QgsExpressionContextScope *contextScope)
Set an expression scope for this symbol.
Definition: qgssymbol.cpp:1401
QgsRenderContext::setExpressionContext
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
Definition: qgsrendercontext.h:572
QgsSymbolLayerUtils::encodeSldUom
static QString encodeSldUom(QgsUnitTypes::RenderUnit unit, double *scaleFactor)
Encodes a render unit into an SLD unit of measure string.
Definition: qgssymbollayerutils.cpp:606
QgsMarkerSymbolLayer::setSize
virtual void setSize(double size)
Sets the symbol size.
Definition: qgssymbollayer.h:647
QgsMarkerSymbolLayer::offset
QPointF offset() const
Returns the marker's offset, which is the horizontal and vertical displacement which the rendered mar...
Definition: qgssymbollayer.h:721
QgsMarkerSymbolLayer::setSizeMapUnitScale
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the symbol's size.
Definition: qgssymbollayer.h:681
qgsgeometrycollection.h
QgsVectorSimplifyMethod::simplifyHints
SimplifyHints simplifyHints() const
Gets the simplification hints of the vector layer managed.
Definition: qgsvectorsimplifymethod.h:64
QgsSymbolLayer::type
QgsSymbol::SymbolType type() const
Definition: qgssymbollayer.h:353
QgsFeature::fields
QgsFields fields
Definition: qgsfeature.h:70
QgsRenderContext::RenderSymbolPreview
@ RenderSymbolPreview
The render is for a symbol preview only and map based properties may not be available,...
Definition: qgsrendercontext.h:82
QgsGeometry::fromQPolygonF
static QgsGeometry fromQPolygonF(const QPolygonF &polygon)
Construct geometry from a QPolygonF.
Definition: qgsgeometry.cpp:3095
QgsFeature
Definition: qgsfeature.h:55
QgsFillSymbol::createSimple
static QgsFillSymbol * createSimple(const QgsStringMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties.
Definition: qgssymbol.cpp:1440
QgsSymbolRenderContext::renderContext
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
Definition: qgssymbol.h:708
QgsLineSymbolLayer::offset
double offset() const
Returns the line's offset.
Definition: qgssymbollayer.h:982
QgsCurve::numPoints
virtual int numPoints() const =0
Returns the number of points in the curve.
QgsSymbol::SymbolType
SymbolType
Type of the symbol.
Definition: qgssymbol.h:85
QgsMarkerSymbol::sizeUnit
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the size units for the whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1642
qgsgeometrygeneratorsymbollayer.h
QgsSymbolLayer::startRender
virtual void startRender(QgsSymbolRenderContext &context)=0
Called before a set of rendering operations commences on the supplied render context.
QgsSymbol::Hybrid
@ Hybrid
Hybrid symbol.
Definition: qgssymbol.h:90
qgslogger.h
QgsRenderContext::painter
QPainter * painter()
Returns the destination QPainter for the render operation.
Definition: qgsrendercontext.h:174
QgsPaintEffect::enabled
bool enabled() const
Returns whether the effect is enabled.
Definition: qgspainteffect.h:198
QgsMarkerSymbol::QgsMarkerSymbol
QgsMarkerSymbol(const QgsSymbolLayerList &layers=QgsSymbolLayerList())
Constructor for QgsMarkerSymbol, with the specified list of initial symbol layers.
Definition: qgssymbol.cpp:1453
QgsSymbol::mForceRHR
bool mForceRHR
Definition: qgssymbol.h:625
QgsRenderContext::setGeometry
void setGeometry(const QgsAbstractGeometry *geometry)
Sets pointer to original (unsegmentized) geometry.
Definition: qgsrendercontext.h:594
QgsSymbol::asImage
QImage asImage(QSize size, QgsRenderContext *customContext=nullptr)
Returns an image of the symbol at the specified size.
Definition: qgssymbol.cpp:604
QgsExpressionContextScope::StaticVariable
Single variable definition for use within a QgsExpressionContextScope.
Definition: qgsexpressioncontext.h:118
QgsCurve::orientation
Orientation orientation() const
Returns the curve's orientation, e.g.
Definition: qgscurve.cpp:249
QgsMarkerSymbol::sizeMapUnitScale
QgsMapUnitScale sizeMapUnitScale() const
Returns the size map unit scale for the whole symbol.
Definition: qgssymbol.cpp:1680
QgsPropertyCollection::isActive
bool isActive(int key) const override
Returns true if the collection contains an active property with the specified key.
Definition: qgspropertycollection.cpp:258
QgsCoordinateTransform
Definition: qgscoordinatetransform.h:52
QgsVectorLayer::clone
QgsVectorLayer * clone() const override
Returns a new instance equivalent to this one.
Definition: qgsvectorlayer.cpp:238
Q_NOWARN_DEPRECATED_PUSH
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:751
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:104
QgsMarkerSymbol::renderPoint
void renderPoint(QPointF point, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
Renders the symbol at the specified point, using the given render context.
Definition: qgssymbol.cpp:1835
MathUtils::angle
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
Definition: MathUtils.cpp:786
QgsFillSymbolLayer::setAngle
void setAngle(double angle)
Definition: qgssymbollayer.h:1111
QgsMapLayer::type
QgsMapLayerType type() const
Returns the type of the layer.
Definition: qgsmaplayer.cpp:129
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:58
qgsproject.h
QgsMarkerSymbolLayer::angle
double angle() const
Returns the rotation angle for the marker, in degrees clockwise from north.
Definition: qgssymbollayer.h:627
QgsRectangle::width
double width() const
Returns the width of the rectangle.
Definition: qgsrectangle.h:202
QgsSymbolLayer::setDataDefinedProperty
virtual void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the layer.
Definition: qgssymbollayer.cpp:112
QgsSymbol::mClipFeaturesToExtent
bool mClipFeaturesToExtent
Definition: qgssymbol.h:624
QgsSurface::boundingBox
QgsRectangle boundingBox() const override
Returns the minimal bounding box for the geometry.
Definition: qgssurface.h:42
QgsRectangle::xMinimum
double xMinimum() const
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:167
QgsWkbTypes::flatType
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:701
QgsMarkerSymbolLayer::setScaleMethod
void setScaleMethod(QgsSymbol::ScaleMethod scaleMethod)
Sets the method to use for scaling the marker's size.
Definition: qgssymbollayer.h:696
QgsGeometry::collectGeometry
static QgsGeometry collectGeometry(const QVector< QgsGeometry > &geometries)
Creates a new multipart geometry from a list of QgsGeometry objects.
Definition: qgsgeometry.cpp:247
QgsMarkerSymbol::setSize
void setSize(double size)
Sets the size for the whole symbol.
Definition: qgssymbol.cpp:1573
QgsSymbolLayerUtils::drawVertexMarker
static void drawVertexMarker(double x, double y, QPainter &p, QgsSymbolLayerUtils::VertexMarkerType type, int markerSize)
Draws a vertex symbol at (painter) coordinates x, y.
Definition: qgssymbollayerutils.cpp:917
QgsMarkerSymbol::setSizeMapUnitScale
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
Sets the size map unit scale for the whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1667
QgsSymbolRenderContext::operator=
QgsSymbolRenderContext & operator=(const QgsSymbolRenderContext &)
Definition: qgssymbol.cpp:1386
QgsCoordinateTransform::transformInPlace
void transformInPlace(double &x, double &y, double &z, TransformDirection direction=ForwardTransform) 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:313
QgsMarkerSymbolLayer::sizeMapUnitScale
const QgsMapUnitScale & sizeMapUnitScale() const
Returns the map unit scale for the symbol's size.
Definition: qgssymbollayer.h:689