QGIS API Documentation  2.13.0-Master
qgssymbolv2.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgssymbolv2.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 "qgssymbolv2.h"
17 #include "qgssymbollayerv2.h"
18 
19 #include "qgslinesymbollayerv2.h"
20 #include "qgsmarkersymbollayerv2.h"
21 #include "qgsfillsymbollayerv2.h"
23 
24 #include "qgslogger.h"
25 #include "qgsrendercontext.h" // for bigSymbolPreview
26 
27 #include "qgsproject.h"
28 #include "qgsstylev2.h"
29 #include "qgspainteffect.h"
30 #include "qgseffectstack.h"
31 
32 #include "qgsdatadefined.h"
33 
34 #include "qgsgeometry.h"
35 #include "qgsmultipointv2.h"
36 #include "qgswkbptr.h"
38 #include "qgsclipper.h"
39 
40 #include <QColor>
41 #include <QImage>
42 #include <QPainter>
43 #include <QSize>
44 #include <QSvgGenerator>
45 
46 #include <cmath>
47 
48 inline
49 QgsDataDefined* rotateWholeSymbol( double additionalRotation, const QgsDataDefined& dd )
50 {
51  QgsDataDefined* rotatedDD = new QgsDataDefined( dd );
52  QString exprString = dd.useExpression() ? dd.expressionString() : dd.field();
53  rotatedDD->setExpressionString( QString::number( additionalRotation ) + " + (" + exprString + ')' );
54  rotatedDD->setUseExpression( true );
55  return rotatedDD;
56 }
57 
58 inline
59 QgsDataDefined* scaleWholeSymbol( double scaleFactor, const QgsDataDefined& dd )
60 {
61  QgsDataDefined* scaledDD = new QgsDataDefined( dd );
62  QString exprString = dd.useExpression() ? dd.expressionString() : dd.field();
63  scaledDD->setExpressionString( QString::number( scaleFactor ) + "*(" + exprString + ')' );
64  scaledDD->setUseExpression( true );
65  return scaledDD;
66 }
67 
68 inline
69 QgsDataDefined* scaleWholeSymbol( double scaleFactorX, double scaleFactorY, const QgsDataDefined& dd )
70 {
71  QgsDataDefined* scaledDD = new QgsDataDefined( dd );
72  QString exprString = dd.useExpression() ? dd.expressionString() : dd.field();
73  scaledDD->setExpressionString(
74  ( !qgsDoubleNear( scaleFactorX, 0.0 ) ? "tostring(" + QString::number( scaleFactorX ) + "*(" + exprString + "))" : "'0'" ) +
75  "|| ',' || " +
76  ( !qgsDoubleNear( scaleFactorY, 0.0 ) ? "tostring(" + QString::number( scaleFactorY ) + "*(" + exprString + "))" : "'0'" ) );
77  scaledDD->setUseExpression( true );
78  return scaledDD;
79 }
80 
81 
83 
85  : mType( type )
86  , mLayers( layers )
87  , mAlpha( 1.0 )
88  , mRenderHints( 0 )
89  , mClipFeaturesToExtent( true )
90  , mLayer( nullptr )
91  , mSymbolRenderContext( nullptr )
92 {
93 
94  // check they're all correct symbol layers
95  for ( int i = 0; i < mLayers.count(); i++ )
96  {
97  if ( !mLayers.at( i ) )
98  {
99  mLayers.removeAt( i-- );
100  }
101  else if ( !mLayers.at( i )->isCompatibleWithSymbol( this ) )
102  {
103  delete mLayers.at( i );
104  mLayers.removeAt( i-- );
105  }
106  }
107 }
108 
109 
110 const unsigned char* QgsSymbolV2::_getLineString( QPolygonF& pts, QgsRenderContext& context, const unsigned char* wkb, bool clipToExtent )
111 {
112  QgsConstWkbPtr wkbPtr( wkb + 1 );
113  unsigned int wkbType, nPoints;
114  wkbPtr >> wkbType >> nPoints;
115 
116  bool hasZValue = QgsWKBTypes::hasZ( static_cast< QgsWKBTypes::Type >( wkbType ) );
117  bool hasMValue = QgsWKBTypes::hasM( static_cast< QgsWKBTypes::Type >( wkbType ) );
118 
119  double x = 0.0;
120  double y = 0.0;
121  const QgsCoordinateTransform* ct = context.coordinateTransform();
122  const QgsMapToPixel& mtp = context.mapToPixel();
123 
124  //apply clipping for large lines to achieve a better rendering performance
125  if ( clipToExtent && nPoints > 1 )
126  {
127  const QgsRectangle& e = context.extent();
128  double cw = e.width() / 10;
129  double ch = e.height() / 10;
130  QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch );
131  wkbPtr = QgsConstWkbPtr( QgsClipper::clippedLineWKB( wkb, clipRect, pts ) );
132  }
133  else
134  {
135  pts.resize( nPoints );
136 
137  QPointF* ptr = pts.data();
138  for ( unsigned int i = 0; i < nPoints; ++i, ++ptr )
139  {
140  wkbPtr >> x >> y;
141  if ( hasZValue )
142  wkbPtr += sizeof( double );
143  if ( hasMValue )
144  wkbPtr += sizeof( double );
145 
146  *ptr = QPointF( x, y );
147  }
148  }
149 
150  //transform the QPolygonF to screen coordinates
151  if ( ct )
152  {
153  ct->transformPolygon( pts );
154  }
155 
156  QPointF* ptr = pts.data();
157  for ( int i = 0; i < pts.size(); ++i, ++ptr )
158  {
159  mtp.transformInPlace( ptr->rx(), ptr->ry() );
160  }
161 
162  return wkbPtr;
163 }
164 
165 const unsigned char* QgsSymbolV2::_getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, const unsigned char* wkb, bool clipToExtent )
166 {
167  QgsConstWkbPtr wkbPtr( wkb + 1 );
168 
169  unsigned int wkbType, numRings;
170  wkbPtr >> wkbType >> numRings;
171 
172  if ( numRings == 0 ) // sanity check for zero rings in polygon
173  return wkbPtr;
174 
175  bool hasZValue = QgsWKBTypes::hasZ( static_cast< QgsWKBTypes::Type >( wkbType ) );
176  bool hasMValue = QgsWKBTypes::hasM( static_cast< QgsWKBTypes::Type >( wkbType ) );
177 
178  double x, y;
179  holes.clear();
180 
181  const QgsCoordinateTransform* ct = context.coordinateTransform();
182  const QgsMapToPixel& mtp = context.mapToPixel();
183  const QgsRectangle& e = context.extent();
184  double cw = e.width() / 10;
185  double ch = e.height() / 10;
186  QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch );
187 
188  for ( unsigned int idx = 0; idx < numRings; idx++ )
189  {
190  unsigned int nPoints;
191  wkbPtr >> nPoints;
192 
193  QPolygonF poly( nPoints );
194 
195  // Extract the points from the WKB and store in a pair of vectors.
196  QPointF* ptr = poly.data();
197  for ( unsigned int jdx = 0; jdx < nPoints; ++jdx, ++ptr )
198  {
199  wkbPtr >> x >> y;
200  if ( hasZValue )
201  wkbPtr += sizeof( double );
202  if ( hasMValue )
203  wkbPtr += sizeof( double );
204 
205  *ptr = QPointF( x, y );
206  }
207 
208  if ( nPoints < 1 )
209  continue;
210 
211  //clip close to view extent, if needed
212  QRectF ptsRect = poly.boundingRect();
213  if ( clipToExtent && !context.extent().contains( ptsRect ) ) QgsClipper::trimPolygon( poly, clipRect );
214 
215  //transform the QPolygonF to screen coordinates
216  if ( ct )
217  {
218  ct->transformPolygon( poly );
219  }
220 
221 
222  ptr = poly.data();
223  for ( int i = 0; i < poly.size(); ++i, ++ptr )
224  {
225  mtp.transformInPlace( ptr->rx(), ptr->ry() );
226  }
227 
228  if ( idx == 0 )
229  pts = poly;
230  else
231  holes.append( poly );
232  }
233 
234  return wkbPtr;
235 }
236 
238 {
239  delete mSymbolRenderContext;
240  // delete all symbol layers (we own them, so it's okay)
241  qDeleteAll( mLayers );
242 }
243 
245 {
246  if ( mLayers.empty() )
247  {
248  return QgsSymbolV2::Mixed;
249  }
250 
252 
253  QgsSymbolV2::OutputUnit unit = ( *it )->outputUnit();
254 
255  for ( ; it != mLayers.constEnd(); ++it )
256  {
257  if (( *it )->outputUnit() != unit )
258  {
259  return QgsSymbolV2::Mixed;
260  }
261  }
262  return unit;
263 }
264 
266 {
267  if ( mLayers.empty() )
268  {
269  return QgsMapUnitScale();
270  }
271 
273  if ( it == mLayers.constEnd() )
274  return QgsMapUnitScale();
275 
276  QgsMapUnitScale scale = ( *it )->mapUnitScale();
277  ++it;
278 
279  for ( ; it != mLayers.constEnd(); ++it )
280  {
281  if (( *it )->mapUnitScale() != scale )
282  {
283  return QgsMapUnitScale();
284  }
285  }
286  return scale;
287 }
288 
290 {
291  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
292  {
293  layer->setOutputUnit( u );
294  }
295 }
296 
298 {
299  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
300  {
301  layer->setMapUnitScale( scale );
302  }
303 }
304 
306 {
307  QgsSymbolV2* s = nullptr;
308 
309  // override global default if project has a default for this type
311  switch ( geomType )
312  {
313  case QGis::Point :
314  defaultSymbol = QgsProject::instance()->readEntry( "DefaultStyles", "/Marker", "" );
315  break;
316  case QGis::Line :
317  defaultSymbol = QgsProject::instance()->readEntry( "DefaultStyles", "/Line", "" );
318  break;
319  case QGis::Polygon :
320  defaultSymbol = QgsProject::instance()->readEntry( "DefaultStyles", "/Fill", "" );
321  break;
322  default:
323  defaultSymbol = "";
324  break;
325  }
326  if ( defaultSymbol != "" )
327  s = QgsStyleV2::defaultStyle()->symbol( defaultSymbol );
328 
329  // if no default found for this type, get global default (as previously)
330  if ( ! s )
331  {
332  switch ( geomType )
333  {
334  case QGis::Point:
335  s = new QgsMarkerSymbolV2();
336  break;
337  case QGis::Line:
338  s = new QgsLineSymbolV2();
339  break;
340  case QGis::Polygon:
341  s = new QgsFillSymbolV2();
342  break;
343  default:
344  QgsDebugMsg( "unknown layer's geometry type" );
345  return nullptr;
346  }
347  }
348 
349  // set alpha transparency
350  s->setAlpha( QgsProject::instance()->readDoubleEntry( "DefaultStyles", "/AlphaInt", 255 ) / 255.0 );
351 
352  // set random color, it project prefs allow
353  if ( defaultSymbol == "" ||
354  QgsProject::instance()->readBoolEntry( "DefaultStyles", "/RandomColors", true ) )
355  {
356  s->setColor( QColor::fromHsv( qrand() % 360, 64 + qrand() % 192, 128 + qrand() % 128 ) );
357  }
358 
359  return s;
360 }
361 
363 {
364  return mLayers.value( layer );
365 }
366 
367 
369 {
370  // fill symbol can contain also line symbol layers for drawing of outlines
371  if ( mType == Fill && layerType == Line )
372  return true;
373 
374  return mType == layerType;
375 }
376 
377 
379 {
380  if ( index < 0 || index > mLayers.count() ) // can be added also after the last index
381  return false;
382 
383  if ( !layer || !layer->isCompatibleWithSymbol( this ) )
384  return false;
385 
386  mLayers.insert( index, layer );
387  return true;
388 }
389 
390 
392 {
393  if ( !layer || !layer->isCompatibleWithSymbol( this ) )
394  return false;
395 
396  mLayers.append( layer );
397  return true;
398 }
399 
400 
402 {
403  if ( index < 0 || index >= mLayers.count() )
404  return false;
405 
406  delete mLayers.at( index );
407  mLayers.removeAt( index );
408  return true;
409 }
410 
411 
413 {
414  if ( index < 0 || index >= mLayers.count() )
415  return nullptr;
416 
417  return mLayers.takeAt( index );
418 }
419 
420 
422 {
423  QgsSymbolLayerV2* oldLayer = mLayers.value( index );
424 
425  if ( oldLayer == layer )
426  return false;
427 
428  if ( !layer || !layer->isCompatibleWithSymbol( this ) )
429  return false;
430 
431  delete oldLayer; // first delete the original layer
432  mLayers[index] = layer; // set new layer
433  return true;
434 }
435 
436 
437 void QgsSymbolV2::startRender( QgsRenderContext& context, const QgsFields* fields )
438 {
439  delete mSymbolRenderContext;
440  mSymbolRenderContext = new QgsSymbolV2RenderContext( context, outputUnit(), mAlpha, false, mRenderHints, nullptr, fields, mapUnitScale() );
441 
442  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, false, mRenderHints, nullptr, fields, mapUnitScale() );
443 
445 
446  mSymbolRenderContext->setExpressionContextScope( scope );
447 
448  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
449  layer->startRender( symbolContext );
450 }
451 
453 {
454  Q_UNUSED( context )
455  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
456  layer->stopRender( *mSymbolRenderContext );
457 
458  delete mSymbolRenderContext;
459  mSymbolRenderContext = nullptr;
460 
461  mLayer = nullptr;
462 }
463 
465 {
466  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
467  {
468  if ( !layer->isLocked() )
469  layer->setColor( color );
470  }
471 }
472 
474 {
475  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
476  {
477  // return color of the first unlocked layer
478  if ( !( *it )->isLocked() )
479  return ( *it )->color();
480  }
481  return QColor( 0, 0, 0 );
482 }
483 
484 void QgsSymbolV2::drawPreviewIcon( QPainter* painter, QSize size, QgsRenderContext* customContext )
485 {
486  QgsRenderContext context = customContext ? *customContext : QgsSymbolLayerV2Utils::createRenderContext( painter );
487  context.setForceVectorOutput( true );
488  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, false, mRenderHints, nullptr, nullptr, mapUnitScale() );
489 
490  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
491  {
492  if ( mType == Fill && layer->type() == Line )
493  {
494  // line symbol layer would normally draw just a line
495  // so we override this case to force it to draw a polygon outline
496  QgsLineSymbolLayerV2* lsl = dynamic_cast<QgsLineSymbolLayerV2*>( layer );
497 
498  if ( lsl )
499  {
500  // from QgsFillSymbolLayerV2::drawPreviewIcon()
501  QPolygonF poly = QRectF( QPointF( 0, 0 ), QPointF( size.width() - 1, size.height() - 1 ) );
502  lsl->startRender( symbolContext );
503  lsl->renderPolygonOutline( poly, nullptr, symbolContext );
504  lsl->stopRender( symbolContext );
505  }
506  }
507  else
508  layer->drawPreviewIcon( symbolContext, size );
509  }
510 }
511 
512 void QgsSymbolV2::exportImage( const QString& path, const QString& format, QSize size )
513 {
514  if ( format.toLower() == "svg" )
515  {
516  QSvgGenerator generator;
517  generator.setFileName( path );
518  generator.setSize( size );
519  generator.setViewBox( QRect( 0, 0, size.height(), size.height() ) );
520 
521  QPainter painter( &generator );
522  drawPreviewIcon( &painter, size );
523  painter.end();
524  }
525  else
526  {
527  QImage image = asImage( size );
528  image.save( path );
529  }
530 }
531 
533 {
534  QImage image( size, QImage::Format_ARGB32_Premultiplied );
535  image.fill( 0 );
536 
537  QPainter p( &image );
538  p.setRenderHint( QPainter::Antialiasing );
539 
540  drawPreviewIcon( &p, size, customContext );
541 
542  return image;
543 }
544 
545 
547 {
548  QImage preview( QSize( 100, 100 ), QImage::Format_ARGB32_Premultiplied );
549  preview.fill( 0 );
550 
551  QPainter p( &preview );
552  p.setRenderHint( QPainter::Antialiasing );
553  p.translate( 0.5, 0.5 ); // shift by half a pixel to avoid blurring due antialising
554 
555  if ( mType == QgsSymbolV2::Marker )
556  {
557  p.setPen( QPen( Qt::gray ) );
558  p.drawLine( 0, 50, 100, 50 );
559  p.drawLine( 50, 0, 50, 100 );
560  }
561 
563  if ( expressionContext )
564  context.setExpressionContext( *expressionContext );
565 
566  startRender( context );
567 
568  if ( mType == QgsSymbolV2::Line )
569  {
570  QPolygonF poly;
571  poly << QPointF( 0, 50 ) << QPointF( 99, 50 );
572  static_cast<QgsLineSymbolV2*>( this )->renderPolyline( poly, nullptr, context );
573  }
574  else if ( mType == QgsSymbolV2::Fill )
575  {
576  QPolygonF polygon;
577  polygon << QPointF( 20, 20 ) << QPointF( 80, 20 ) << QPointF( 80, 80 ) << QPointF( 20, 80 ) << QPointF( 20, 20 );
578  static_cast<QgsFillSymbolV2*>( this )->renderPolygon( polygon, nullptr, nullptr, context );
579  }
580  else // marker
581  {
582  static_cast<QgsMarkerSymbolV2*>( this )->renderPoint( QPointF( 50, 50 ), nullptr, context );
583  }
584 
585  stopRender( context );
586  return preview;
587 }
588 
589 
591 {
592  QString t;
593  switch ( type() )
594  {
595  case QgsSymbolV2::Marker:
596  t = "MARKER";
597  break;
598  case QgsSymbolV2::Line:
599  t = "LINE";
600  break;
601  case QgsSymbolV2::Fill:
602  t = "FILL";
603  break;
604  default:
605  Q_ASSERT( 0 && "unknown symbol type" );
606  }
607  QString s = QString( "%1 SYMBOL (%2 layers) color %3" ).arg( t ).arg( mLayers.count() ).arg( QgsSymbolLayerV2Utils::encodeColor( color() ) );
608 
609  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
610  {
611  // TODO:
612  }
613  return s;
614 }
615 
616 void QgsSymbolV2::toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const
617 {
618  props[ "alpha" ] = QString::number( alpha() );
619  double scaleFactor = 1.0;
620  props[ "uom" ] = QgsSymbolLayerV2Utils::encodeSldUom( outputUnit(), &scaleFactor );
621  props[ "uomScale" ] = ( !qgsDoubleNear( scaleFactor, 1.0 ) ? QString::number( scaleFactor ) : "" );
622 
623  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
624  {
625  ( *it )->toSld( doc, element, props );
626  }
627 }
628 
630 {
632  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
633  {
634  QgsSymbolLayerV2* layer = ( *it )->clone();
635  layer->setLocked(( *it )->isLocked() );
636  layer->setRenderingPass(( *it )->renderingPass() );
637  lst.append( layer );
638  }
639  return lst;
640 }
641 
643 {
644  Q_ASSERT( layer->type() == Hybrid );
645 
647 
648  QgsPaintEffect* effect = generatorLayer->paintEffect();
649  if ( effect && effect->enabled() )
650  {
651  QPainter* p = context.renderContext().painter();
652  p->save();
653 
654  effect->begin( context.renderContext() );
655  generatorLayer->render( context );
656  effect->end( context.renderContext() );
657 
658  p->restore();
659  }
660  else
661  {
662  generatorLayer->render( context );
663  }
664 }
665 
667 {
668  QSet<QString> attributes;
670  for ( ; sIt != mLayers.constEnd(); ++sIt )
671  {
672  if ( *sIt )
673  {
674  attributes.unite(( *sIt )->usedAttributes() );
675  }
676  }
677  return attributes;
678 }
679 
681 {
682  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
683  {
684  if ( layer->hasDataDefinedProperties() )
685  return true;
686  }
687  return false;
688 }
689 
690 void QgsSymbolV2::renderFeature( const QgsFeature& feature, QgsRenderContext& context, int layer, bool selected, bool drawVertexMarker, int currentVertexMarkerType, int currentVertexMarkerSize )
691 {
692  const QgsGeometry* geom = feature.constGeometry();
693  if ( !geom || !geom->geometry() )
694  {
695  return;
696  }
697 
698  const QgsGeometry* segmentizedGeometry = geom;
699  bool deleteSegmentizedGeometry = false;
700  context.setGeometry( geom->geometry() );
701 
702  bool tileMapRendering = context.testFlag( QgsRenderContext::RenderMapTile );
703 
704  //convert curve types to normal point/line/polygon ones
705  if ( QgsWKBTypes::isCurvedType( geom->geometry()->wkbType() ) )
706  {
707  QgsAbstractGeometryV2* g = geom->geometry()->segmentize();
708  if ( !g )
709  {
710  return;
711  }
712  segmentizedGeometry = new QgsGeometry( g );
713  deleteSegmentizedGeometry = true;
714  }
715 
716  if ( mSymbolRenderContext->expressionContextScope() )
717  {
718  context.expressionContext().appendScope( mSymbolRenderContext->expressionContextScope() );
720  mSymbolRenderContext->expressionContextScope()->setVariable( QgsExpressionContext::EXPR_GEOMETRY_PART_COUNT, segmentizedGeometry->geometry()->partCount() );
722  }
723 
724  switch ( QgsWKBTypes::flatType( segmentizedGeometry->geometry()->wkbType() ) )
725  {
726  case QgsWKBTypes::Point:
727  {
728  QPointF pt;
729  if ( mType != QgsSymbolV2::Marker )
730  {
731  QgsDebugMsg( "point can be drawn only with marker symbol!" );
732  break;
733  }
734 
735  const QgsPointV2* point = static_cast< const QgsPointV2* >( segmentizedGeometry->geometry() );
736 
737  _getPoint( pt, context, point );
738  ( static_cast<QgsMarkerSymbolV2*>( this ) )->renderPoint( pt, &feature, context, layer, selected );
739 
741  {
742  //draw debugging rect
743  context.painter()->setPen( Qt::red );
744  context.painter()->setBrush( QColor( 255, 0, 0, 100 ) );
745  context.painter()->drawRect( static_cast<QgsMarkerSymbolV2*>( this )->bounds( pt, context ) );
746  }
747  }
748  break;
750  {
751  QPolygonF pts;
752  if ( mType != QgsSymbolV2::Line )
753  {
754  QgsDebugMsg( "linestring can be drawn only with line symbol!" );
755  break;
756  }
757  _getLineString( pts, context, segmentizedGeometry->asWkb(), !tileMapRendering && clipFeaturesToExtent() );
758  static_cast<QgsLineSymbolV2*>( this )->renderPolyline( pts, &feature, context, layer, selected );
759  }
760  break;
762  {
763  QPolygonF pts;
764  QList<QPolygonF> holes;
765  if ( mType != QgsSymbolV2::Fill )
766  {
767  QgsDebugMsg( "polygon can be drawn only with fill symbol!" );
768  break;
769  }
770  _getPolygon( pts, holes, context, segmentizedGeometry->asWkb(), !tileMapRendering && clipFeaturesToExtent() );
771  static_cast<QgsFillSymbolV2*>( this )->renderPolygon( pts, ( !holes.isEmpty() ? &holes : nullptr ), &feature, context, layer, selected );
772  }
773  break;
774 
776  {
777  QPointF pt;
778 
779  if ( mType != QgsSymbolV2::Marker )
780  {
781  QgsDebugMsg( "multi-point can be drawn only with marker symbol!" );
782  break;
783  }
784 
785  QgsMultiPointV2* mp = static_cast< QgsMultiPointV2* >( segmentizedGeometry->geometry() );
786 
787  for ( int i = 0; i < mp->numGeometries(); ++i )
788  {
790 
791  const QgsPointV2* point = static_cast< const QgsPointV2* >( mp->geometryN( i ) );
792  _getPoint( pt, context, point );
793  static_cast<QgsMarkerSymbolV2*>( this )->renderPoint( pt, &feature, context, layer, selected );
794  }
795  }
796  break;
797 
800  {
801  QPolygonF pts;
802 
803  if ( mType != QgsSymbolV2::Line )
804  {
805  QgsDebugMsg( "multi-linestring can be drawn only with line symbol!" );
806  break;
807  }
808 
809  QgsConstWkbPtr wkbPtr( segmentizedGeometry->asWkb() + 1 + sizeof( int ) );
810  unsigned int num;
811  wkbPtr >> num;
812  const unsigned char* ptr = wkbPtr;
813 
814  const QgsGeometryCollectionV2* geomCollection = dynamic_cast<const QgsGeometryCollectionV2*>( geom->geometry() );
815 
816  for ( unsigned int i = 0; i < num; ++i )
817  {
819 
820  if ( geomCollection )
821  {
822  context.setGeometry( geomCollection->geometryN( i ) );
823  }
824  ptr = QgsConstWkbPtr( _getLineString( pts, context, ptr, !tileMapRendering && clipFeaturesToExtent() ) );
825  static_cast<QgsLineSymbolV2*>( this )->renderPolyline( pts, &feature, context, layer, selected );
826  }
827  }
828  break;
829 
832  {
833  if ( mType != QgsSymbolV2::Fill )
834  {
835  QgsDebugMsg( "multi-polygon can be drawn only with fill symbol!" );
836  break;
837  }
838 
839  QgsConstWkbPtr wkbPtr( segmentizedGeometry->asWkb() + 1 + sizeof( int ) );
840  unsigned int num;
841  wkbPtr >> num;
842  const unsigned char* ptr = wkbPtr;
843 
844  QPolygonF pts;
845  QList<QPolygonF> holes;
846 
847  const QgsGeometryCollectionV2* geomCollection = dynamic_cast<const QgsGeometryCollectionV2*>( geom->geometry() );
848 
849  for ( unsigned int i = 0; i < num; ++i )
850  {
852 
853  if ( geomCollection )
854  {
855  context.setGeometry( geomCollection->geometryN( i ) );
856  }
857  ptr = _getPolygon( pts, holes, context, ptr, !tileMapRendering && clipFeaturesToExtent() );
858  static_cast<QgsFillSymbolV2*>( this )->renderPolygon( pts, ( !holes.isEmpty() ? &holes : nullptr ), &feature, context, layer, selected );
859  }
860  break;
861  }
862  default:
863  QgsDebugMsg( QString( "feature %1: unsupported wkb type 0x%2 for rendering" ).arg( feature.id() ).arg( geom->wkbType(), 0, 16 ) );
864  }
865 
866  if ( drawVertexMarker )
867  {
868  const QgsCoordinateTransform* ct = context.coordinateTransform();
869  const QgsMapToPixel& mtp = context.mapToPixel();
870 
871  QgsPointV2 vertexPoint;
872  QgsVertexId vertexId;
873  double x, y, z;
874  QPointF mapPoint;
875  while ( geom->geometry()->nextVertex( vertexId, vertexPoint ) )
876  {
877  //transform
878  x = vertexPoint.x();
879  y = vertexPoint.y();
880  z = vertexPoint.z();
881  if ( ct )
882  {
883  ct->transformInPlace( x, y, z );
884  }
885  mapPoint.setX( x );
886  mapPoint.setY( y );
887  mtp.transformInPlace( mapPoint.rx(), mapPoint.ry() );
888  QgsVectorLayer::drawVertexMarker( mapPoint.x(), mapPoint.y(), *context.painter(),
889  static_cast< QgsVectorLayer::VertexMarkerType >( currentVertexMarkerType ),
890  currentVertexMarkerSize );
891  }
892  }
893 
894  if ( deleteSegmentizedGeometry )
895  {
896  delete segmentizedGeometry;
897  }
898 
899  context.expressionContext().popScope();
900 }
901 
903 {
904  return mSymbolRenderContext;
905 }
906 
908 
909 
911  : mRenderContext( c ),
912  mExpressionContextScope( nullptr ),
913  mOutputUnit( u ),
914  mMapUnitScale( mapUnitScale ),
915  mAlpha( alpha ),
916  mSelected( selected ),
917  mRenderHints( renderHints ),
918  mFeature( f ),
919  mFields( fields )
920 {
921 }
922 
924 {
925  delete mExpressionContextScope;
926 }
927 
929 {
930  mRenderContext.expressionContext().setOriginalValueVariable( value );
931 }
932 
933 double QgsSymbolV2RenderContext::outputLineWidth( double width ) const
934 {
935  return QgsSymbolLayerV2Utils::convertToPainterUnits( mRenderContext, width, mOutputUnit, mMapUnitScale );
936 }
937 
938 double QgsSymbolV2RenderContext::outputPixelSize( double size ) const
939 {
940  return size * QgsSymbolLayerV2Utils::pixelSizeScaleFactor( mRenderContext, mOutputUnit, mMapUnitScale );
941 }
942 
944 {
945  // This is just a dummy implementation of assignment.
946  // sip 4.7 generates a piece of code that needs this function to exist.
947  // It's not generated automatically by the compiler because of
948  // mRenderContext member which is a reference (and thus can't be changed).
949  Q_ASSERT( false );
950  return *this;
951 }
952 
954 {
955  return mExpressionContextScope;
956 }
957 
959 {
960  mExpressionContextScope = contextScope;
961 }
962 
964 
966 {
968  if ( !sl )
969  return nullptr;
970 
971  QgsSymbolLayerV2List layers;
972  layers.append( sl );
973  return new QgsMarkerSymbolV2( layers );
974 }
975 
977 {
979  if ( !sl )
980  return nullptr;
981 
982  QgsSymbolLayerV2List layers;
983  layers.append( sl );
984  return new QgsLineSymbolV2( layers );
985 }
986 
988 {
990  if ( !sl )
991  return nullptr;
992 
993  QgsSymbolLayerV2List layers;
994  layers.append( sl );
995  return new QgsFillSymbolV2( layers );
996 }
997 
999 
1001  : QgsSymbolV2( Marker, layers )
1002 {
1003  if ( mLayers.isEmpty() )
1005 }
1006 
1008 {
1009  double origAngle = angle();
1010  double angleDiff = ang - origAngle;
1011  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1012  {
1013  QgsMarkerSymbolLayerV2* markerLayer = dynamic_cast<QgsMarkerSymbolLayerV2*>( layer );
1014  if ( markerLayer )
1015  markerLayer->setAngle( markerLayer->angle() + angleDiff );
1016  }
1017 }
1018 
1020 {
1021  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1022  {
1023  if ( layer->type() != QgsSymbolV2::Marker )
1024  continue;
1025  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1026  return markerLayer->angle();
1027  }
1028  return 0;
1029 }
1030 
1031 void QgsMarkerSymbolV2::setLineAngle( double lineAng )
1032 {
1033  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1034  {
1035  if ( layer->type() != QgsSymbolV2::Marker )
1036  continue;
1037  QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
1038  markerLayer->setLineAngle( lineAng );
1039  }
1040 }
1041 
1043 {
1044  const double symbolRotation = angle();
1045 
1046  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1047  {
1048  if ( layer->type() != QgsSymbolV2::Marker )
1049  continue;
1050  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1051  if ( dd.hasDefaultValues() )
1052  {
1053  layer->removeDataDefinedProperty( "angle" );
1054  }
1055  else
1056  {
1057  if ( qgsDoubleNear( markerLayer->angle(), symbolRotation ) )
1058  {
1059  layer->setDataDefinedProperty( "angle", new QgsDataDefined( dd ) );
1060  }
1061  else
1062  {
1063  QgsDataDefined* rotatedDD = rotateWholeSymbol( markerLayer->angle() - symbolRotation, dd );
1064  layer->setDataDefinedProperty( "angle", rotatedDD );
1065  }
1066  }
1067  }
1068 }
1069 
1071 {
1072  const double symbolRotation = angle();
1073  QgsDataDefined* symbolDD = nullptr;
1074 
1075  // find the base of the "en masse" pattern
1076  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1077  {
1078  if ( layer->type() != QgsSymbolV2::Marker )
1079  continue;
1080  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1081  if ( qgsDoubleNear( markerLayer->angle(), symbolRotation ) && markerLayer->getDataDefinedProperty( "angle" ) )
1082  {
1083  symbolDD = markerLayer->getDataDefinedProperty( "angle" );
1084  break;
1085  }
1086  }
1087 
1088  if ( !symbolDD )
1089  return QgsDataDefined();
1090 
1091  // check that all layer's angle expressions match the "en masse" pattern
1092  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1093  {
1094  if ( layer->type() != QgsSymbolV2::Marker )
1095  continue;
1096  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1097  QgsDataDefined* layerAngleDD = markerLayer->getDataDefinedProperty( "angle" );
1098 
1099  if ( qgsDoubleNear( markerLayer->angle(), symbolRotation ) )
1100  {
1101  if ( !layerAngleDD || *layerAngleDD != *symbolDD )
1102  return QgsDataDefined();
1103  }
1104  else
1105  {
1106  QScopedPointer< QgsDataDefined > rotatedDD( rotateWholeSymbol( markerLayer->angle() - symbolRotation, *symbolDD ) );
1107  if ( !layerAngleDD || *layerAngleDD != *( rotatedDD.data() ) )
1108  return QgsDataDefined();
1109  }
1110  }
1111  return QgsDataDefined( *symbolDD );
1112 }
1113 
1114 
1116 {
1117  double origSize = size();
1118 
1119  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1120  {
1121  if ( layer->type() != QgsSymbolV2::Marker )
1122  continue;
1123  QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
1124  if ( qgsDoubleNear( markerLayer->size(), origSize ) )
1125  markerLayer->setSize( s );
1126  else if ( !qgsDoubleNear( origSize, 0.0 ) )
1127  {
1128  // proportionally scale size
1129  markerLayer->setSize( markerLayer->size() * s / origSize );
1130  }
1131  // also scale offset to maintain relative position
1132  if ( !qgsDoubleNear( origSize, 0.0 ) && ( !qgsDoubleNear( markerLayer->offset().x(), 0.0 ) || !qgsDoubleNear( markerLayer->offset().y(), 0.0 ) ) )
1133  markerLayer->setOffset( QPointF( markerLayer->offset().x() * s / origSize,
1134  markerLayer->offset().y() * s / origSize ) );
1135  }
1136 }
1137 
1139 {
1140  // return size of the largest symbol
1141  double maxSize = 0;
1142  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1143  {
1144  if ( layer->type() != QgsSymbolV2::Marker )
1145  continue;
1146  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1147  double lsize = markerLayer->size();
1148  if ( lsize > maxSize )
1149  maxSize = lsize;
1150  }
1151  return maxSize;
1152 }
1153 
1155 {
1156  const double symbolSize = size();
1157 
1158  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1159  {
1160  if ( layer->type() != QgsSymbolV2::Marker )
1161  continue;
1162  QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
1163 
1164  if ( dd.hasDefaultValues() )
1165  {
1166  markerLayer->removeDataDefinedProperty( "size" );
1167  markerLayer->removeDataDefinedProperty( "offset" );
1168  }
1169  else
1170  {
1171  if ( qgsDoubleNear( symbolSize, 0.0 ) || qgsDoubleNear( markerLayer->size(), symbolSize ) )
1172  {
1173  markerLayer->setDataDefinedProperty( "size", new QgsDataDefined( dd ) );
1174  }
1175  else
1176  {
1177  markerLayer->setDataDefinedProperty( "size", scaleWholeSymbol( markerLayer->size() / symbolSize, dd ) );
1178  }
1179 
1180  if ( !qgsDoubleNear( markerLayer->offset().x(), 0.0 ) || !qgsDoubleNear( markerLayer->offset().y(), 0.0 ) )
1181  {
1182  markerLayer->setDataDefinedProperty( "offset", scaleWholeSymbol(
1183  markerLayer->offset().x() / symbolSize,
1184  markerLayer->offset().y() / symbolSize, dd ) );
1185  }
1186  }
1187  }
1188 }
1189 
1191 {
1192  const double symbolSize = size();
1193 
1194  QgsDataDefined* symbolDD = nullptr;
1195 
1196  // find the base of the "en masse" pattern
1197  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1198  {
1199  if ( layer->type() != QgsSymbolV2::Marker )
1200  continue;
1201  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1202  if ( qgsDoubleNear( markerLayer->size(), symbolSize ) && markerLayer->getDataDefinedProperty( "size" ) )
1203  {
1204  symbolDD = markerLayer->getDataDefinedProperty( "size" );
1205  break;
1206  }
1207  }
1208 
1209  if ( !symbolDD )
1210  return QgsDataDefined();
1211 
1212  // check that all layers size expressions match the "en masse" pattern
1213  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1214  {
1215  if ( layer->type() != QgsSymbolV2::Marker )
1216  continue;
1217  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1218 
1219  QgsDataDefined* layerSizeDD = markerLayer->getDataDefinedProperty( "size" );
1220  QgsDataDefined* layerOffsetDD = markerLayer->getDataDefinedProperty( "offset" );
1221 
1222  if ( qgsDoubleNear( markerLayer->size(), symbolSize ) )
1223  {
1224  if ( !layerSizeDD || *layerSizeDD != *symbolDD )
1225  return QgsDataDefined();
1226  }
1227  else
1228  {
1229  if ( qgsDoubleNear( symbolSize, 0.0 ) )
1230  return QgsDataDefined();
1231 
1232  QScopedPointer< QgsDataDefined > scaledDD( scaleWholeSymbol( markerLayer->size() / symbolSize, *symbolDD ) );
1233  if ( !layerSizeDD || *layerSizeDD != *( scaledDD.data() ) )
1234  return QgsDataDefined();
1235  }
1236 
1237  QScopedPointer< QgsDataDefined > scaledOffsetDD( scaleWholeSymbol( markerLayer->offset().x() / symbolSize, markerLayer->offset().y() / symbolSize, *symbolDD ) );
1238  if ( layerOffsetDD && *layerOffsetDD != *( scaledOffsetDD.data() ) )
1239  return QgsDataDefined();
1240  }
1241 
1242  return QgsDataDefined( *symbolDD );
1243 }
1244 
1246 {
1247  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1248  {
1249  if ( layer->type() != QgsSymbolV2::Marker )
1250  continue;
1251  QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
1252  markerLayer->setScaleMethod( scaleMethod );
1253  }
1254 }
1255 
1257 {
1258  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1259  {
1260  if ( layer->type() != QgsSymbolV2::Marker )
1261  continue;
1262  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1263  // return scale method of the first symbol layer
1264  return markerLayer->scaleMethod();
1265  }
1266 
1267  return DEFAULT_SCALE_METHOD;
1268 }
1269 
1270 void QgsMarkerSymbolV2::renderPointUsingLayer( QgsMarkerSymbolLayerV2* layer, QPointF point, QgsSymbolV2RenderContext& context )
1271 {
1272  static QPointF nullPoint( 0, 0 );
1273 
1274  QgsPaintEffect* effect = layer->paintEffect();
1275  if ( effect && effect->enabled() )
1276  {
1277  QPainter* p = context.renderContext().painter();
1278  p->save();
1279  p->translate( point );
1280 
1281  effect->begin( context.renderContext() );
1282  layer->renderPoint( nullPoint, context );
1283  effect->end( context.renderContext() );
1284 
1285  p->restore();
1286  }
1287  else
1288  {
1289  layer->renderPoint( point, context );
1290  }
1291 }
1292 
1293 void QgsMarkerSymbolV2::renderPoint( QPointF point, const QgsFeature* f, QgsRenderContext& context, int layerIdx, bool selected )
1294 {
1295  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, selected, mRenderHints, f, nullptr, mapUnitScale() );
1296 
1297  if ( layerIdx != -1 )
1298  {
1299  QgsSymbolLayerV2* symbolLayer = mLayers.value( layerIdx );
1300  if ( symbolLayer )
1301  {
1302  if ( symbolLayer->type() == QgsSymbolV2::Marker )
1303  {
1304  QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( symbolLayer );
1305  renderPointUsingLayer( markerLayer, point, symbolContext );
1306  }
1307  else
1308  renderUsingLayer( symbolLayer, symbolContext );
1309  }
1310  return;
1311  }
1312 
1313  Q_FOREACH ( QgsSymbolLayerV2* symbolLayer, mLayers )
1314  {
1315  if ( symbolLayer->type() == QgsSymbolV2::Marker )
1316  {
1317  QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( symbolLayer );
1318  renderPointUsingLayer( markerLayer, point, symbolContext );
1319  }
1320  else
1321  renderUsingLayer( symbolLayer, symbolContext );
1322  }
1323 }
1324 
1326 {
1327  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, false, mRenderHints, nullptr, nullptr, mapUnitScale() );
1328 
1329  QRectF bound;
1330  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1331  {
1332  if ( layer->type() == QgsSymbolV2::Marker )
1333  {
1335  if ( bound.isNull() )
1336  bound = symbolLayer->bounds( point, symbolContext );
1337  else
1338  bound = bound.united( symbolLayer->bounds( point, symbolContext ) );
1339  }
1340  }
1341  return bound;
1342 }
1343 
1345 {
1346  QgsMarkerSymbolV2* cloneSymbol = new QgsMarkerSymbolV2( cloneLayers() );
1347  cloneSymbol->setAlpha( mAlpha );
1348  cloneSymbol->setLayer( mLayer );
1350  return cloneSymbol;
1351 }
1352 
1353 
1355 // LINE
1356 
1358  : QgsSymbolV2( Line, layers )
1359 {
1360  if ( mLayers.isEmpty() )
1362 }
1363 
1365 {
1366  double origWidth = width();
1367 
1368  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1369  {
1370  QgsLineSymbolLayerV2* lineLayer = dynamic_cast<QgsLineSymbolLayerV2*>( layer );
1371 
1372  if ( lineLayer )
1373  {
1374  if ( qgsDoubleNear( lineLayer->width(), origWidth ) )
1375  {
1376  lineLayer->setWidth( w );
1377  }
1378  else if ( !qgsDoubleNear( origWidth, 0.0 ) )
1379  {
1380  // proportionally scale the width
1381  lineLayer->setWidth( lineLayer->width() * w / origWidth );
1382  }
1383  // also scale offset to maintain relative position
1384  if ( !qgsDoubleNear( origWidth, 0.0 ) && !qgsDoubleNear( lineLayer->offset(), 0.0 ) )
1385  lineLayer->setOffset( lineLayer->offset() * w / origWidth );
1386  }
1387  }
1388 }
1389 
1391 {
1392  double maxWidth = 0;
1393  if ( mLayers.isEmpty() )
1394  return maxWidth;
1395 
1396  Q_FOREACH ( QgsSymbolLayerV2* symbolLayer, mLayers )
1397  {
1398  const QgsLineSymbolLayerV2* lineLayer = dynamic_cast<QgsLineSymbolLayerV2*>( symbolLayer );
1399  if ( lineLayer )
1400  {
1401  double width = lineLayer->width();
1402  if ( width > maxWidth )
1403  maxWidth = width;
1404  }
1405  }
1406  return maxWidth;
1407 }
1408 
1410 {
1411  const double symbolWidth = width();
1412 
1413  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1414  {
1415  QgsLineSymbolLayerV2* lineLayer = dynamic_cast<QgsLineSymbolLayerV2*>( layer );
1416 
1417  if ( lineLayer )
1418  {
1419  if ( dd.hasDefaultValues() )
1420  {
1421  lineLayer->removeDataDefinedProperty( "width" );
1422  lineLayer->removeDataDefinedProperty( "offset" );
1423  }
1424  else
1425  {
1426  if ( qgsDoubleNear( symbolWidth, 0.0 ) || qgsDoubleNear( lineLayer->width(), symbolWidth ) )
1427  {
1428  lineLayer->setDataDefinedProperty( "width", new QgsDataDefined( dd ) );
1429  }
1430  else
1431  {
1432  lineLayer->setDataDefinedProperty( "width", scaleWholeSymbol( lineLayer->width() / symbolWidth, dd ) );
1433  }
1434 
1435  if ( !qgsDoubleNear( lineLayer->offset(), 0.0 ) )
1436  {
1437  lineLayer->setDataDefinedProperty( "offset", scaleWholeSymbol( lineLayer->offset() / symbolWidth, dd ) );
1438  }
1439  }
1440  }
1441  }
1442 }
1443 
1445 {
1446  const double symbolWidth = width();
1447 
1448  QgsDataDefined* symbolDD = nullptr;
1449 
1450  // find the base of the "en masse" pattern
1451  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
1452  {
1453  const QgsLineSymbolLayerV2* layer = dynamic_cast<const QgsLineSymbolLayerV2*>( *it );
1454  if ( layer && qgsDoubleNear( layer->width(), symbolWidth ) && layer->getDataDefinedProperty( "width" ) )
1455  {
1456  symbolDD = layer->getDataDefinedProperty( "width" );
1457  break;
1458  }
1459  }
1460 
1461  if ( !symbolDD )
1462  return QgsDataDefined();
1463 
1464  // check that all layers width expressions match the "en masse" pattern
1465  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1466  {
1467  if ( layer->type() != QgsSymbolV2::Line )
1468  continue;
1469  const QgsLineSymbolLayerV2* lineLayer = static_cast<const QgsLineSymbolLayerV2*>( layer );
1470 
1471  QgsDataDefined* layerWidthDD = lineLayer->getDataDefinedProperty( "width" );
1472  QgsDataDefined* layerOffsetDD = lineLayer->getDataDefinedProperty( "offset" );
1473 
1474  if ( qgsDoubleNear( lineLayer->width(), symbolWidth ) )
1475  {
1476  if ( !layerWidthDD || *layerWidthDD != *symbolDD )
1477  return QgsDataDefined();
1478  }
1479  else
1480  {
1481  if ( qgsDoubleNear( symbolWidth, 0.0 ) )
1482  return QgsDataDefined();
1483 
1484  QScopedPointer< QgsDataDefined > scaledDD( scaleWholeSymbol( lineLayer->width() / symbolWidth, *symbolDD ) );
1485  if ( !layerWidthDD || *layerWidthDD != *( scaledDD.data() ) )
1486  return QgsDataDefined();
1487  }
1488 
1489  QScopedPointer< QgsDataDefined > scaledOffsetDD( scaleWholeSymbol( lineLayer->offset() / symbolWidth, *symbolDD ) );
1490  if ( layerOffsetDD && *layerOffsetDD != *( scaledOffsetDD.data() ) )
1491  return QgsDataDefined();
1492  }
1493 
1494  return QgsDataDefined( *symbolDD );
1495 }
1496 
1497 void QgsLineSymbolV2::renderPolyline( const QPolygonF& points, const QgsFeature* f, QgsRenderContext& context, int layerIdx, bool selected )
1498 {
1499  //save old painter
1500  QPainter* renderPainter = context.painter();
1501  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, selected, mRenderHints, f, nullptr, mapUnitScale() );
1502 
1503  if ( layerIdx != -1 )
1504  {
1505  QgsSymbolLayerV2* symbolLayer = mLayers.value( layerIdx );
1506  if ( symbolLayer )
1507  {
1508  if ( symbolLayer->type() == QgsSymbolV2::Line )
1509  {
1510  QgsLineSymbolLayerV2* lineLayer = static_cast<QgsLineSymbolLayerV2*>( symbolLayer );
1511  renderPolylineUsingLayer( lineLayer, points, symbolContext );
1512  }
1513  else
1514  renderUsingLayer( symbolLayer, symbolContext );
1515  }
1516  return;
1517  }
1518 
1519  Q_FOREACH ( QgsSymbolLayerV2* symbolLayer, mLayers )
1520  {
1521  if ( symbolLayer->type() == QgsSymbolV2::Line )
1522  {
1523  QgsLineSymbolLayerV2* lineLayer = static_cast<QgsLineSymbolLayerV2*>( symbolLayer );
1524  renderPolylineUsingLayer( lineLayer, points, symbolContext );
1525  }
1526  else
1527  {
1528  renderUsingLayer( symbolLayer, symbolContext );
1529  }
1530  }
1531 
1532  context.setPainter( renderPainter );
1533 }
1534 
1535 void QgsLineSymbolV2::renderPolylineUsingLayer( QgsLineSymbolLayerV2 *layer, const QPolygonF &points, QgsSymbolV2RenderContext &context )
1536 {
1537  QgsPaintEffect* effect = layer->paintEffect();
1538  if ( effect && effect->enabled() )
1539  {
1540  QPainter* p = context.renderContext().painter();
1541  p->save();
1542  p->translate( points.boundingRect().topLeft() );
1543 
1544  effect->begin( context.renderContext() );
1545  layer->renderPolyline( points.translated( -points.boundingRect().topLeft() ), context );
1546  effect->end( context.renderContext() );
1547 
1548  p->restore();
1549  }
1550  else
1551  {
1552  layer->renderPolyline( points, context );
1553  }
1554 }
1555 
1556 
1558 {
1559  QgsLineSymbolV2* cloneSymbol = new QgsLineSymbolV2( cloneLayers() );
1560  cloneSymbol->setAlpha( mAlpha );
1561  cloneSymbol->setLayer( mLayer );
1563  return cloneSymbol;
1564 }
1565 
1567 // FILL
1568 
1570  : QgsSymbolV2( Fill, layers )
1571 {
1572  if ( mLayers.isEmpty() )
1574 }
1575 
1576 void QgsFillSymbolV2::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, const QgsFeature* f, QgsRenderContext& context, int layerIdx, bool selected )
1577 {
1578  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, selected, mRenderHints, f, nullptr, mapUnitScale() );
1579 
1580  if ( layerIdx != -1 )
1581  {
1582  QgsSymbolLayerV2* symbolLayer = mLayers.value( layerIdx );
1583  if ( symbolLayer )
1584  {
1585  if ( symbolLayer->type() == Fill || symbolLayer->type() == Line )
1586  renderPolygonUsingLayer( symbolLayer, points, rings, symbolContext );
1587  else
1588  renderUsingLayer( symbolLayer, symbolContext );
1589  }
1590  return;
1591  }
1592 
1593  Q_FOREACH ( QgsSymbolLayerV2* symbolLayer, mLayers )
1594  {
1595  if ( symbolLayer->type() == Fill || symbolLayer->type() == Line )
1596  renderPolygonUsingLayer( symbolLayer, points, rings, symbolContext );
1597  else
1598  renderUsingLayer( symbolLayer, symbolContext );
1599  }
1600 }
1601 
1602 void QgsFillSymbolV2::renderPolygonUsingLayer( QgsSymbolLayerV2* layer, const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context )
1603 {
1604  QgsSymbolV2::SymbolType layertype = layer->type();
1605 
1606  QgsPaintEffect* effect = layer->paintEffect();
1607  if ( effect && effect->enabled() )
1608  {
1609  QRectF bounds = polygonBounds( points, rings );
1610  QList<QPolygonF>* translatedRings = translateRings( rings, -bounds.left(), -bounds.top() );
1611 
1612  QPainter* p = context.renderContext().painter();
1613  p->save();
1614  p->translate( bounds.topLeft() );
1615 
1616  effect->begin( context.renderContext() );
1617  if ( layertype == QgsSymbolV2::Fill )
1618  {
1619  ( static_cast<QgsFillSymbolLayerV2*>( layer ) )->renderPolygon( points.translated( -bounds.topLeft() ), translatedRings, context );
1620  }
1621  else if ( layertype == QgsSymbolV2::Line )
1622  {
1623  ( static_cast<QgsLineSymbolLayerV2*>( layer ) )->renderPolygonOutline( points.translated( -bounds.topLeft() ), translatedRings, context );
1624  }
1625  delete translatedRings;
1626 
1627  effect->end( context.renderContext() );
1628  p->restore();
1629  }
1630  else
1631  {
1632  if ( layertype == QgsSymbolV2::Fill )
1633  {
1634  ( static_cast<QgsFillSymbolLayerV2*>( layer ) )->renderPolygon( points, rings, context );
1635  }
1636  else if ( layertype == QgsSymbolV2::Line )
1637  {
1638  ( static_cast<QgsLineSymbolLayerV2*>( layer ) )->renderPolygonOutline( points, rings, context );
1639  }
1640  }
1641 }
1642 
1643 QRectF QgsFillSymbolV2::polygonBounds( const QPolygonF& points, const QList<QPolygonF>* rings ) const
1644 {
1645  QRectF bounds = points.boundingRect();
1646  if ( rings )
1647  {
1649  for ( ; it != rings->constEnd(); ++it )
1650  {
1651  bounds = bounds.united(( *it ).boundingRect() );
1652  }
1653  }
1654  return bounds;
1655 }
1656 
1657 QList<QPolygonF>* QgsFillSymbolV2::translateRings( const QList<QPolygonF>* rings, double dx, double dy ) const
1658 {
1659  if ( !rings )
1660  return nullptr;
1661 
1662  QList<QPolygonF>* translatedRings = new QList<QPolygonF>;
1664  for ( ; it != rings->constEnd(); ++it )
1665  {
1666  translatedRings->append(( *it ).translated( dx, dy ) );
1667  }
1668  return translatedRings;
1669 }
1670 
1672 {
1673  QgsFillSymbolV2* cloneSymbol = new QgsFillSymbolV2( cloneLayers() );
1674  cloneSymbol->setAlpha( mAlpha );
1675  cloneSymbol->setLayer( mLayer );
1677  return cloneSymbol;
1678 }
1679 
1681 {
1682  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1683  {
1684  if ( layer->type() != QgsSymbolV2::Fill )
1685  continue;
1686 
1687  QgsFillSymbolLayerV2* fillLayer = static_cast<QgsFillSymbolLayerV2*>( layer );
1688 
1689  if ( fillLayer )
1690  fillLayer->setAngle( angle );
1691  }
1692 }
1693 
1694 
QgsFeatureId id() const
Get the feature ID for this feature.
Definition: qgsfeature.cpp:65
virtual void renderPoint(QPointF point, QgsSymbolV2RenderContext &context)=0
virtual void setMapUnitScale(const QgsMapUnitScale &scale)
QgsFillSymbolV2(const QgsSymbolLayerV2List &layers=QgsSymbolLayerV2List())
void setForceVectorOutput(bool force)
void clear()
void setLocked(bool locked)
bool deleteSymbolLayer(int index)
delete symbol layer at specified index
static unsigned index
QgsWKBTypes::Type wkbType() const
Returns the WKB type of the geometry.
void setViewBox(const QRect &viewBox)
A rectangle specified with double values.
Definition: qgsrectangle.h:35
void renderPolygon(const QPolygonF &points, QList< QPolygonF > *rings, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
static QgsMarkerSymbolV2 * createSimple(const QgsStringMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
void setClipFeaturesToExtent(bool clipFeaturesToExtent)
Sets whether features drawn by the symbol should be clipped to the render context&#39;s extent...
Definition: qgssymbolv2.h:212
OutputUnit
The unit of the output.
Definition: qgssymbolv2.h:59
virtual void setOutputUnit(QgsSymbolV2::OutputUnit unit)
int width() const
bool mClipFeaturesToExtent
Definition: qgssymbolv2.h:316
void setDataDefinedAngle(const QgsDataDefined &dd)
Set data defined angle for whole symbol (including all symbol layers).
A container class for data source field mapping or expression.
bool end()
GeometryType
Definition: qgis.h:111
void setSize(const QSize &size)
virtual double width() const
virtual QgsLineSymbolV2 * clone() const override
void setRenderHint(RenderHint hint, bool on)
const QgsVectorLayer * mLayer
Definition: qgssymbolv2.h:318
double x() const
Returns the point&#39;s x-coordinate.
Definition: qgspointv2.h:68
SymbolType type() const
Definition: qgssymbolv2.h:101
void transformPolygon(QPolygonF &poly, TransformDirection direction=ForwardTransform) const
virtual bool isCompatibleWithSymbol(QgsSymbolV2 *symbol) const
Returns if the layer can be used below the specified symbol.
QSet< QString > usedAttributes() const
Return a list of attributes required to render this feature.
QString field() const
Get the field which this QgsDataDefined represents.
virtual QRectF bounds(QPointF point, QgsSymbolV2RenderContext &context)
Returns the approximate bounding box of the marker symbol layer, taking into account any data defined...
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:703
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:196
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
void setDataDefinedSize(const QgsDataDefined &dd)
Set data defined size for whole symbol (including all symbol layers).
QgsAbstractGeometryV2 * geometry() const
Returns the underlying geometry store.
bool save(const QString &fileName, const char *format, int quality) const
static QString encodeColor(const QColor &color)
static QString encodeSldUom(QgsSymbolV2::OutputUnit unit, double *scaleFactor)
void setScaleMethod(QgsSymbolV2::ScaleMethod scaleMethod)
double size() const
static const unsigned char * clippedLineWKB(const unsigned char *wkb, const QgsRectangle &clipExtent, QPolygonF &line)
Reads a polyline from WKB and clips it to clipExtent.
Definition: qgsclipper.cpp:40
QgsDataDefined dataDefinedSize() const
Returns data defined size for whole symbol (including all symbol layers).
static QgsFillSymbolV2 * createSimple(const QgsStringMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties. ...
bool contains(const QgsRectangle &rect) const
return true when rectangle contains other rectangle
const T & at(int i) const
VertexMarkerType
Editing vertex markers.
void setOffset(QPointF offset)
void removeAt(int i)
QPolygonF translated(qreal dx, qreal dy) const
bool enabled() const
Returns whether the effect is enabled.
Base class for visual effects which can be applied to QPicture drawings.
bool changeSymbolLayer(int index, QgsSymbolLayerV2 *layer)
delete layer at specified index and set a new one
QgsSymbolV2RenderContext(QgsRenderContext &c, QgsSymbolV2::OutputUnit u, qreal alpha=1.0, bool selected=false, int renderHints=0, const QgsFeature *f=nullptr, const QgsFields *fields=nullptr, const QgsMapUnitScale &mapUnitScale=QgsMapUnitScale())
ScaleMethod scaleMethod()
void save()
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for data defined symbology.
static void _getPoint(QPointF &pt, QgsRenderContext &context, const QgsPointV2 *point)
Creates a point in screen coordinates from a QgsPointV2 in map coordinates.
Definition: qgssymbolv2.h:258
Abstract base class for all geometries.
QgsMapUnitScale mapUnitScale() const
Container of fields for a vector layer.
Definition: qgsfield.h:189
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:76
qreal top() const
Line symbol.
Definition: qgssymbolv2.h:76
QString expressionString() const
Returns the expression string of this QgsDataDefined.
T takeAt(int i)
const QgsRectangle & extent() const
Multi point geometry collection.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:187
void drawLine(const QLineF &line)
void renderFeature(const QgsFeature &feature, QgsRenderContext &context, int layer=-1, bool selected=false, bool drawVertexMarker=false, int currentVertexMarkerType=0, int currentVertexMarkerSize=0)
Render a feature.
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:656
const QgsCoordinateTransform * coordinateTransform() const
void setExpressionContextScope(QgsExpressionContextScope *contextScope)
Set an expression scope for this symbol.
SymbolType mType
Definition: qgssymbolv2.h:309
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
virtual void removeDataDefinedProperty(const QString &property)
Removes a data defined property from the layer.
void drawPreviewIcon(QPainter *painter, QSize size, QgsRenderContext *customContext=nullptr)
Draw icon of the symbol that occupyies area given by size using the painter.
qreal left() const
void setVariable(const QString &name, const QVariant &value)
Convenience method for setting a variable in the context scope by name and value. ...
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Definition: qgis.h:285
static double pixelSizeScaleFactor(const QgsRenderContext &c, QgsSymbolV2::OutputUnit u, const QgsMapUnitScale &scale=QgsMapUnitScale())
Returns scale factor painter units -> pixel dimensions.
void setWidth(double width)
QgsDataDefined * scaleWholeSymbol(double scaleFactor, const QgsDataDefined &dd)
Definition: qgssymbolv2.cpp:59
Marker symbol.
Definition: qgssymbolv2.h:75
QgsDataDefined dataDefinedWidth() const
Returns data defined size for whole symbol (including all symbol layers).
void setMapUnitScale(const QgsMapUnitScale &scale)
void setAngle(double angle)
const QgsVectorLayer * layer() const
Definition: qgssymbolv2.h:238
virtual void startRender(QgsSymbolV2RenderContext &context)=0
T value(int i) const
double y() const
Returns the point&#39;s y-coordinate.
Definition: qgspointv2.h:74
QColor fromHsv(int h, int s, int v, int a)
T * data()
void drawRect(const QRectF &rectangle)
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:34
void setUseExpression(bool use)
Controls if the field or the expression part is active.
void setColor(const QColor &color)
Mixed units in symbol layers.
Definition: qgssymbolv2.h:63
void transformInPlace(double &x, double &y, double &z, TransformDirection direction=ForwardTransform) const
void transformInPlace(double &x, double &y) const
Transform device coordinates to map (world) coordinates.
static QgsRenderContext createRenderContext(QPainter *p)
Creates a render context for a pixel based device.
QString readEntry(const QString &scope, const QString &key, const QString &def=QString::null, bool *ok=nullptr) const
QString number(int n, int base)
QgsSymbolLayerV2List mLayers
Definition: qgssymbolv2.h:310
int count(const T &value) const
qreal x() const
qreal y() const
void append(const T &value)
double width() const
QgsSymbolLayerV2List cloneLayers() const
Retrieve a cloned list of all layers that make up this symbol.
void setOffset(double offset)
bool appendSymbolLayer(QgsSymbolLayerV2 *layer)
Append symbol layer at the end of the list Ownership will be transferred.
void resize(int size)
bool empty() const
void startRender(QgsRenderContext &context, const QgsFields *fields=nullptr)
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:201
void fill(uint pixelValue)
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:186
static double convertToPainterUnits(const QgsRenderContext &c, double size, QgsSymbolV2::OutputUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale())
Converts a size from the specied units to painter units.
void setLineAngle(double lineAngle)
Sets the line angle modification for the symbol&#39;s angle.
Utility class for identifying a unique vertex within a geometry.
double z() const
Returns the point&#39;s z-coordinate.
Definition: qgspointv2.h:80
qreal alpha() const
Get alpha transparency 1 for opaque, 0 for invisible.
Definition: qgssymbolv2.h:197
static QgsLineSymbolV2 * createSimple(const QgsStringMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties. ...
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
static bool isCurvedType(Type type)
Returns true if the WKB type is a curved type or can contain curved geometries.
Definition: qgswkbtypes.h:520
void setPen(const QColor &color)
Q_DECL_DEPRECATED bool isSymbolLayerCompatible(SymbolType layerType)
check whether a symbol layer type can be used within the symbol (marker-marker, line-line, fill-fill/line)
void toSld(QDomDocument &doc, QDomElement &element, QgsStringMap props) const
void setRenderingPass(int renderingPass)
#define DEFAULT_SCALE_METHOD
void setLayer(const QgsVectorLayer *layer)
Definition: qgssymbolv2.h:237
Point geometry type, with support for z-dimension and m-values.
Definition: qgspointv2.h:34
bool isEmpty() const
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
virtual void setWidth(double width)
static QgsStyleV2 * defaultStyle()
return default application-wide style
Definition: qgsstylev2.cpp:51
QPointF topLeft() const
void renderPolyline(const QPolygonF &points, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
QgsMarkerSymbolV2(const QgsSymbolLayerV2List &layers=QgsSymbolLayerV2List())
void setAngle(double angle)
double angle() const
void setAngle(double angle)
Draw bounds of symbols (for debugging/testing)
void setBrush(const QBrush &brush)
void setPainter(QPainter *p)
void setSize(double size)
QGis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
qreal mAlpha
Symbol opacity (in the range 0 - 1)
Definition: qgssymbolv2.h:313
virtual int partCount() const =0
Returns count of parts contained in the geometry.
QgsSymbolV2RenderContext & operator=(const QgsSymbolV2RenderContext &)
QRectF united(const QRectF &rectangle) const
virtual void renderPolygonOutline(const QPolygonF &points, QList< QPolygonF > *rings, QgsSymbolV2RenderContext &context)
QgsSymbolV2(SymbolType type, const QgsSymbolLayerV2List &layers)
Definition: qgssymbolv2.cpp:84
virtual bool nextVertex(QgsVertexId &id, QgsPointV2 &vertex) const =0
Returns next vertex id and coordinates.
QgsDataDefined * rotateWholeSymbol(double additionalRotation, const QgsDataDefined &dd)
Definition: qgssymbolv2.cpp:49
Single scope for storing variables and functions for use within a QgsExpressionContext.
QRectF bounds(QPointF point, QgsRenderContext &context) const
Returns the approximate bounding box of the marker symbol, which includes the bounding box of all sym...
virtual bool hasDataDefinedProperties() const
Checks whether the layer has any associated data defined properties.
static void drawVertexMarker(double x, double y, QPainter &p, QgsVectorLayer::VertexMarkerType type, int vertexSize)
Draws a vertex symbol at (screen) coordinates x, y.
void setLineAngle(double lineAngle)
Sets the line angle modification for the symbol&#39;s angle.
QgsSymbolV2::ScaleMethod scaleMethod() const
QgsSymbolV2::SymbolType type() const
bool useExpression() const
Returns if the field or the expression part is active.
T * data() const
double ANALYSIS_EXPORT angle(Point3D *p1, Point3D *p2, Point3D *p3, Point3D *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
iterator end()
QString toLower() const
virtual ~QgsSymbolV2()
virtual void renderPolyline(const QPolygonF &points, QgsSymbolV2RenderContext &context)=0
QgsSymbolV2 * symbol(const QString &name)
return a NEW copy of symbol
Definition: qgsstylev2.cpp:164
static const unsigned char * _getPolygon(QPolygonF &pts, QList< QPolygonF > &holes, QgsRenderContext &context, const unsigned char *wkb, bool clipToExtent=true)
Creates a polygon in screen coordinates from a wkb string in map coordinates.
bool isNull() const
virtual QgsFillSymbolV2 * clone() const override
QImage bigSymbolPreviewImage(QgsExpressionContext *expressionContext=nullptr)
Returns a large (roughly 100x100 pixel) preview image for the symbol.
void setFileName(const QString &fileName)
void exportImage(const QString &path, const QString &format, QSize size)
export symbol as image format. PNG and SVG supported
QgsExpressionContext & expressionContext()
Gets the expression context.
virtual QgsAbstractGeometryV2 * segmentize() const
Returns a version of the geometry without curves.
void renderUsingLayer(QgsSymbolLayerV2 *layer, QgsSymbolV2RenderContext &context)
Renders a context using a particular symbol layer without passing in a geometry.
SymbolType
Type of the symbol.
Definition: qgssymbolv2.h:73
void restore()
void setDataDefinedWidth(const QgsDataDefined &dd)
Set data defined width for whole symbol (including all symbol layers).
Hybrid symbol.
Definition: qgssymbolv2.h:78
int numGeometries() const
Returns the number of geometries within the collection.
QgsExpressionContextScope * expressionContextScope()
This scope is always available when a symbol of this type is being rendered.
static const unsigned char * _getLineString(QPolygonF &pts, QgsRenderContext &context, const unsigned char *wkb, bool clipToExtent=true)
Creates a line string in screen coordinates from a wkb string in map coordinates. ...
Contains information about the context of a rendering operation.
QRectF boundingRect() const
QPainter * painter()
QgsDataDefined dataDefinedAngle() const
Returns data defined angle for whole symbol (including all symbol layers).
void stopRender(QgsRenderContext &context)
bool insertSymbolLayer(int index, QgsSymbolLayerV2 *layer)
Insert symbol layer to specified index Ownership will be transferred.
QSet< T > & unite(const QSet< T > &other)
static QgsSymbolV2 * defaultSymbol(QGis::GeometryType geomType)
return new default symbol for specified geometry type
ScaleMethod
Scale method.
Definition: qgssymbolv2.h:84
Struct for storing maximum and minimum scales for measurements in map units.
bool isLocked() const
void insert(int i, const T &value)
QImage asImage(QSize size, QgsRenderContext *customContext=nullptr)
Generate symbol as image.
double offset() const
QgsRenderContext & renderContext()
Definition: qgssymbolv2.h:336
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
virtual QgsDataDefined * getDataDefinedProperty(const QString &property) const
Returns the data defined property corresponding to the specified property key.
void setX(qreal x)
void setY(qreal y)
static QgsProject * instance()
access to canonical QgsProject instance
Definition: qgsproject.cpp:379
int height() const
Fill symbol.
Definition: qgssymbolv2.h:77
QgsSymbolV2::OutputUnit outputUnit() const
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
Definition: qgsfeature.cpp:82
qreal & rx()
qreal & ry()
Class for doing transforms between two map coordinate systems.
const QgsAbstractGeometryV2 * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
void renderPoint(QPointF point, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
void translate(const QPointF &offset)
bool testFlag(Flag flag) const
Check whether a particular flag is enabled.
const QgsMapToPixel & mapToPixel() const
virtual void setColor(const QColor &color)
The fill color.
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:366
QgsSymbolLayerV2 * takeSymbolLayer(int index)
Remove symbol layer from the list and return pointer to it.
bool hasDefaultValues() const
Returns whether the data defined container is set to all the default values, ie, disabled, with empty expression and no assigned field.
double outputPixelSize(double size) const
double outputLineWidth(double width) const
QgsSymbolLayerV2 * symbolLayer(int layer)
Returns a specific symbol layers contained in the symbol.
QgsExpressionContextScope * popScope()
Removes the last scope from the expression context and return it.
const_iterator constEnd() const
QString dump() const
virtual void drawPreviewIcon(QgsSymbolV2RenderContext &context, QSize size)=0
const_iterator constBegin() const
Draw map such that there are no problems between adjacent tiles.
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:206
static void trimPolygon(QPolygonF &pts, const QgsRectangle &clipRect)
Definition: qgsclipper.h:180
static const QString EXPR_GEOMETRY_PART_NUM
Inbuilt variable name for geometry part number variable.
void setSize(double size)
int size() const
void setAngle(double angle)
bool clipFeaturesToExtent() const
Returns whether features drawn by the symbol will be clipped to the render context&#39;s extent...
Definition: qgssymbolv2.h:222
QPointF offset() const
static const QString EXPR_GEOMETRY_PART_COUNT
Inbuilt variable name for geometry part count variable.
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for the context.
virtual void end(QgsRenderContext &context)
Ends interception of paint operations to a render context, and draws the result to the render context...
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
const unsigned char * asWkb() const
Returns the buffer containing this geometry in WKB format.
static QgsExpressionContextScope * updateSymbolScope(const QgsSymbolV2 *symbol, QgsExpressionContextScope *symbolScope=nullptr)
Updates a symbol scope related to a QgsSymbolV2 to an expression context.
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:191
virtual void stopRender(QgsSymbolV2RenderContext &context)=0
void setExpressionString(const QString &expr)
Sets the expression for this QgsDataDefined.
void setOutputUnit(QgsSymbolV2::OutputUnit u)
void setAlpha(qreal alpha)
Set alpha transparency 1 for opaque, 0 for invisible.
Definition: qgssymbolv2.h:199
iterator begin()
bool hasDataDefinedProperties() const
Returns whether the symbol utilises any data defined properties.
void setScaleMethod(QgsSymbolV2::ScaleMethod scaleMethod)
void setGeometry(const QgsAbstractGeometryV2 *geometry)
Sets pointer to original (unsegmentized) geometry.
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
virtual void begin(QgsRenderContext &context)
Begins intercepting paint operations to a render context.
QgsSymbolV2RenderContext * symbolRenderContext()
Returns the symbol render context.
QgsLineSymbolV2(const QgsSymbolLayerV2List &layers=QgsSymbolLayerV2List())
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
virtual QgsMarkerSymbolV2 * clone() const override
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the layer.
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:211
QColor color() const
int mRenderHints
Definition: qgssymbolv2.h:315
virtual Q_DECL_DEPRECATED void setDataDefinedProperty(const QString &property, const QString &expressionString)
Sets a data defined expression for a property.
int renderHints() const
Definition: qgssymbolv2.h:202