QGIS API Documentation  2.11.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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"
22 
23 #include "qgslogger.h"
24 #include "qgsrendercontext.h" // for bigSymbolPreview
25 
26 #include "qgsproject.h"
27 #include "qgsstylev2.h"
28 #include "qgspainteffect.h"
29 #include "qgseffectstack.h"
30 
31 #include "qgsdatadefined.h"
32 
33 #include <QColor>
34 #include <QImage>
35 #include <QPainter>
36 #include <QSize>
37 #include <QSvgGenerator>
38 
39 #include <cmath>
40 
41 inline
42 QgsDataDefined* rotateWholeSymbol( double additionalRotation, const QgsDataDefined& dd )
43 {
44  QgsDataDefined* rotatedDD = new QgsDataDefined( dd );
45  rotatedDD->setUseExpression( true );
46  QString exprString = dd.useExpression() ? dd.expressionString() : dd.field();
47  rotatedDD->setExpressionString( QString::number( additionalRotation ) + " + (" + exprString + ")" );
48  return rotatedDD;
49 }
50 
51 inline
52 QgsDataDefined* scaleWholeSymbol( double scaleFactor, const QgsDataDefined& dd )
53 {
54  QgsDataDefined* scaledDD = new QgsDataDefined( dd );
55  scaledDD->setUseExpression( true );
56  QString exprString = dd.useExpression() ? dd.expressionString() : dd.field();
57  scaledDD->setExpressionString( QString::number( scaleFactor ) + "*(" + exprString + ")" );
58  return scaledDD;
59 }
60 
61 inline
62 QgsDataDefined* scaleWholeSymbol( double scaleFactorX, double scaleFactorY, const QgsDataDefined& dd )
63 {
64  QgsDataDefined* scaledDD = new QgsDataDefined( dd );
65  scaledDD->setUseExpression( true );
66  QString exprString = dd.useExpression() ? dd.expressionString() : dd.field();
67  scaledDD->setExpressionString(
68  ( scaleFactorX ? "tostring(" + QString::number( scaleFactorX ) + "*(" + exprString + "))" : "'0'" ) +
69  "|| ',' || " +
70  ( scaleFactorY ? "tostring(" + QString::number( scaleFactorY ) + "*(" + exprString + "))" : "'0'" ) );
71  return scaledDD;
72 }
73 
74 
76 
78  : mType( type )
79  , mLayers( layers )
80  , mAlpha( 1.0 )
81  , mRenderHints( 0 )
82  , mClipFeaturesToExtent( true )
83  , mLayer( 0 )
84 {
85 
86  // check they're all correct symbol layers
87  for ( int i = 0; i < mLayers.count(); i++ )
88  {
89  if ( mLayers[i] == NULL )
90  {
91  mLayers.removeAt( i-- );
92  }
93  else if ( !isSymbolLayerCompatible( mLayers[i]->type() ) )
94  {
95  delete mLayers[i];
96  mLayers.removeAt( i-- );
97  }
98  }
99 }
100 
102 {
103  // delete all symbol layers (we own them, so it's okay)
104  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
105  delete *it;
106 }
107 
109 {
110  if ( mLayers.empty() )
111  {
112  return QgsSymbolV2::Mixed;
113  }
114 
116 
117  QgsSymbolV2::OutputUnit unit = ( *it )->outputUnit();
118 
119  for ( ; it != mLayers.constEnd(); ++it )
120  {
121  if (( *it )->outputUnit() != unit )
122  {
123  return QgsSymbolV2::Mixed;
124  }
125  }
126  return unit;
127 }
128 
130 {
131  if ( mLayers.empty() )
132  {
133  return QgsMapUnitScale();
134  }
135 
137  if ( it == mLayers.constEnd() )
138  return QgsMapUnitScale();
139 
140  QgsMapUnitScale scale = ( *it )->mapUnitScale();
141  ++it;
142 
143  for ( ; it != mLayers.constEnd(); ++it )
144  {
145  if (( *it )->mapUnitScale() != scale )
146  {
147  return QgsMapUnitScale();
148  }
149  }
150  return scale;
151 }
152 
154 {
156  for ( ; it != mLayers.end(); ++it )
157  {
158  ( *it )->setOutputUnit( u );
159  }
160 }
161 
163 {
165  for ( ; it != mLayers.end(); ++it )
166  {
167  ( *it )->setMapUnitScale( scale );
168  }
169 }
170 
172 {
173  QgsSymbolV2* s = 0;
174 
175  // override global default if project has a default for this type
177  switch ( geomType )
178  {
179  case QGis::Point :
180  defaultSymbol = QgsProject::instance()->readEntry( "DefaultStyles", "/Marker", "" );
181  break;
182  case QGis::Line :
183  defaultSymbol = QgsProject::instance()->readEntry( "DefaultStyles", "/Line", "" );
184  break;
185  case QGis::Polygon :
186  defaultSymbol = QgsProject::instance()->readEntry( "DefaultStyles", "/Fill", "" );
187  break;
188  default: defaultSymbol = ""; break;
189  }
190  if ( defaultSymbol != "" )
191  s = QgsStyleV2::defaultStyle()->symbol( defaultSymbol );
192 
193  // if no default found for this type, get global default (as previously)
194  if ( ! s )
195  {
196  switch ( geomType )
197  {
198  case QGis::Point: s = new QgsMarkerSymbolV2(); break;
199  case QGis::Line: s = new QgsLineSymbolV2(); break;
200  case QGis::Polygon: s = new QgsFillSymbolV2(); break;
201  default: QgsDebugMsg( "unknown layer's geometry type" ); return NULL;
202  }
203  }
204 
205  // set alpha transparency
206  s->setAlpha( QgsProject::instance()->readDoubleEntry( "DefaultStyles", "/AlphaInt", 255 ) / 255.0 );
207 
208  // set random color, it project prefs allow
209  if ( defaultSymbol == "" ||
210  QgsProject::instance()->readBoolEntry( "DefaultStyles", "/RandomColors", true ) )
211  {
212  s->setColor( QColor::fromHsv( qrand() % 360, 64 + qrand() % 192, 128 + qrand() % 128 ) );
213  }
214 
215  return s;
216 }
217 
219 {
220  if ( layer < 0 || layer >= mLayers.count() )
221  return NULL;
222 
223  return mLayers[layer];
224 }
225 
226 
228 {
229  // fill symbol can contain also line symbol layers for drawing of outlines
230  if ( mType == Fill && t == Line )
231  return true;
232 
233  return mType == t;
234 }
235 
236 
238 {
239  if ( index < 0 || index > mLayers.count() ) // can be added also after the last index
240  return false;
241  if ( layer == NULL || !isSymbolLayerCompatible( layer->type() ) )
242  return false;
243 
244  mLayers.insert( index, layer );
245  return true;
246 }
247 
248 
250 {
251  if ( layer == NULL || !isSymbolLayerCompatible( layer->type() ) )
252  return false;
253 
254  mLayers.append( layer );
255  return true;
256 }
257 
258 
260 {
261  if ( index < 0 || index >= mLayers.count() )
262  return false;
263 
264  delete mLayers[index];
265  mLayers.removeAt( index );
266  return true;
267 }
268 
269 
271 {
272  if ( index < 0 || index >= mLayers.count() )
273  return NULL;
274 
275  return mLayers.takeAt( index );
276 }
277 
278 
280 {
281  if ( index < 0 || index >= mLayers.count() )
282  return false;
283  if ( layer == NULL || !isSymbolLayerCompatible( layer->type() ) )
284  return false;
285 
286  delete mLayers[index]; // first delete the original layer
287  mLayers[index] = layer; // set new layer
288  return true;
289 }
290 
291 
292 void QgsSymbolV2::startRender( QgsRenderContext& context, const QgsFields* fields )
293 {
294  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, false, mRenderHints, 0, fields, mapUnitScale() );
295 
296 
297  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
298  ( *it )->startRender( symbolContext );
299 }
300 
302 {
303  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, false, mRenderHints, 0, 0, mapUnitScale() );
304 
305  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
306  ( *it )->stopRender( symbolContext );
307 
308  mLayer = NULL;
309 }
310 
311 void QgsSymbolV2::setColor( const QColor& color )
312 {
313  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
314  {
315  if ( !( *it )->isLocked() )
316  ( *it )->setColor( color );
317  }
318 }
319 
321 {
322  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
323  {
324  // return color of the first unlocked layer
325  if ( !( *it )->isLocked() )
326  return ( *it )->color();
327  }
328  return QColor( 0, 0, 0 );
329 }
330 
331 void QgsSymbolV2::drawPreviewIcon( QPainter* painter, QSize size, QgsRenderContext* customContext )
332 {
333  QgsRenderContext context = customContext ? *customContext : QgsSymbolLayerV2Utils::createRenderContext( painter );
334  context.setForceVectorOutput( true );
335  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, false, mRenderHints, 0, 0, mapUnitScale() );
336 
337  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
338  {
339  if ( mType == Fill && ( *it )->type() == Line )
340  {
341  // line symbol layer would normally draw just a line
342  // so we override this case to force it to draw a polygon outline
344 
345  // from QgsFillSymbolLayerV2::drawPreviewIcon()
346  QPolygonF poly = QRectF( QPointF( 0, 0 ), QPointF( size.width() - 1, size.height() - 1 ) );
347  lsl->startRender( symbolContext );
348  lsl->renderPolygonOutline( poly, NULL, symbolContext );
349  lsl->stopRender( symbolContext );
350  }
351  else
352  ( *it )->drawPreviewIcon( symbolContext, size );
353  }
354 }
355 
356 void QgsSymbolV2::exportImage( QString path, QString format, QSize size )
357 {
358  if ( format.toLower() == "svg" )
359  {
360  QSvgGenerator generator;
361  generator.setFileName( path );
362  generator.setSize( size );
363  generator.setViewBox( QRect( 0, 0, size.height(), size.height() ) );
364 
365  QPainter painter( &generator );
366  drawPreviewIcon( &painter, size );
367  painter.end();
368  }
369  else
370  {
371  QImage image = asImage( size );
372  image.save( path );
373  }
374 }
375 
377 {
378  QImage image( size, QImage::Format_ARGB32_Premultiplied );
379  image.fill( 0 );
380 
381  QPainter p( &image );
382  p.setRenderHint( QPainter::Antialiasing );
383 
384  drawPreviewIcon( &p, size, customContext );
385 
386  return image;
387 }
388 
389 
391 {
392  QImage preview( QSize( 100, 100 ), QImage::Format_ARGB32_Premultiplied );
393  preview.fill( 0 );
394 
395  QPainter p( &preview );
396  p.setRenderHint( QPainter::Antialiasing );
397  p.translate( 0.5, 0.5 ); // shift by half a pixel to avoid blurring due antialising
398 
399  if ( mType == QgsSymbolV2::Marker )
400  {
401  p.setPen( QPen( Qt::gray ) );
402  p.drawLine( 0, 50, 100, 50 );
403  p.drawLine( 50, 0, 50, 100 );
404  }
405 
407  startRender( context );
408 
409  if ( mType == QgsSymbolV2::Line )
410  {
411  QPolygonF poly;
412  poly << QPointF( 0, 50 ) << QPointF( 99, 50 );
413  static_cast<QgsLineSymbolV2*>( this )->renderPolyline( poly, 0, context );
414  }
415  else if ( mType == QgsSymbolV2::Fill )
416  {
417  QPolygonF polygon;
418  polygon << QPointF( 20, 20 ) << QPointF( 80, 20 ) << QPointF( 80, 80 ) << QPointF( 20, 80 ) << QPointF( 20, 20 );
419  static_cast<QgsFillSymbolV2*>( this )->renderPolygon( polygon, NULL, 0, context );
420  }
421  else // marker
422  {
423  static_cast<QgsMarkerSymbolV2*>( this )->renderPoint( QPointF( 50, 50 ), 0, context );
424  }
425 
426  stopRender( context );
427  return preview;
428 }
429 
430 
432 {
433  QString t;
434  switch ( type() )
435  {
436  case QgsSymbolV2::Marker: t = "MARKER"; break;
437  case QgsSymbolV2::Line: t = "LINE"; break;
438  case QgsSymbolV2::Fill: t = "FILL"; break;
439  default: Q_ASSERT( 0 && "unknown symbol type" );
440  }
441  QString s = QString( "%1 SYMBOL (%2 layers) color %3" ).arg( t ).arg( mLayers.count() ).arg( QgsSymbolLayerV2Utils::encodeColor( color() ) );
442 
443  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
444  {
445  // TODO:
446  }
447  return s;
448 }
449 
450 void QgsSymbolV2::toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const
451 {
452  props[ "alpha" ] = QString::number( alpha() );
453  double scaleFactor = 1.0;
454  props[ "uom" ] = QgsSymbolLayerV2Utils::encodeSldUom( outputUnit(), &scaleFactor );
455  props[ "uomScale" ] = scaleFactor != 1 ? QString::number( scaleFactor ) : "";
456 
457  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
458  {
459  ( *it )->toSld( doc, element, props );
460  }
461 }
462 
464 {
466  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
467  {
468  QgsSymbolLayerV2* layer = ( *it )->clone();
469  layer->setLocked(( *it )->isLocked() );
470  layer->setRenderingPass(( *it )->renderingPass() );
471  lst.append( layer );
472  }
473  return lst;
474 }
475 
477 {
478  QSet<QString> attributes;
480  for ( ; sIt != mLayers.constEnd(); ++sIt )
481  {
482  if ( *sIt )
483  {
484  attributes.unite(( *sIt )->usedAttributes() );
485  }
486  }
487  return attributes;
488 }
489 
491 
492 
493 QgsSymbolV2RenderContext::QgsSymbolV2RenderContext( QgsRenderContext& c, QgsSymbolV2::OutputUnit u, qreal alpha, bool selected, int renderHints, const QgsFeature* f, const QgsFields* fields, const QgsMapUnitScale& mapUnitScale )
494  : mRenderContext( c ), mOutputUnit( u ), mMapUnitScale( mapUnitScale ), mAlpha( alpha ), mSelected( selected ), mRenderHints( renderHints ), mFeature( f ), mFields( fields )
495 {
496 
497 }
498 
500 {
501 
502 }
503 
504 
505 double QgsSymbolV2RenderContext::outputLineWidth( double width ) const
506 {
507  return width * QgsSymbolLayerV2Utils::lineWidthScaleFactor( mRenderContext, mOutputUnit, mMapUnitScale );
508 }
509 
510 double QgsSymbolV2RenderContext::outputPixelSize( double size ) const
511 {
512  return size * QgsSymbolLayerV2Utils::pixelSizeScaleFactor( mRenderContext, mOutputUnit, mMapUnitScale );
513 }
514 
516 {
517  // This is just a dummy implementation of assignment.
518  // sip 4.7 generates a piece of code that needs this function to exist.
519  // It's not generated automatically by the compiler because of
520  // mRenderContext member which is a reference (and thus can't be changed).
521  Q_ASSERT( false );
522  return *this;
523 }
524 
526 
528 {
530  if ( sl == NULL )
531  return NULL;
532 
533  QgsSymbolLayerV2List layers;
534  layers.append( sl );
535  return new QgsMarkerSymbolV2( layers );
536 }
537 
539 {
541  if ( sl == NULL )
542  return NULL;
543 
544  QgsSymbolLayerV2List layers;
545  layers.append( sl );
546  return new QgsLineSymbolV2( layers );
547 }
548 
550 {
552  if ( sl == NULL )
553  return NULL;
554 
555  QgsSymbolLayerV2List layers;
556  layers.append( sl );
557  return new QgsFillSymbolV2( layers );
558 }
559 
561 
563  : QgsSymbolV2( Marker, layers )
564 {
565  if ( mLayers.count() == 0 )
567 }
568 
569 void QgsMarkerSymbolV2::setAngle( double ang )
570 {
571  double origAngle = angle();
572  double angleDiff = ang - origAngle;
573  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
574  {
576  layer->setAngle( layer->angle() + angleDiff );
577  }
578 }
579 
581 {
583 
584  if ( it == mLayers.end() )
585  return 0;
586 
587  // return angle of the first symbol layer
588  const QgsMarkerSymbolLayerV2* layer = static_cast<const QgsMarkerSymbolLayerV2 *>( *it );
589  return layer->angle();
590 }
591 
592 void QgsMarkerSymbolV2::setLineAngle( double lineAng )
593 {
594  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
595  {
597  layer->setLineAngle( lineAng );
598  }
599 }
600 
602 {
603  const double symbolRotation = angle();
604 
605  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
606  {
607  QgsMarkerSymbolLayerV2* layer = static_cast<QgsMarkerSymbolLayerV2 *>( *it );
608  if ( dd.hasDefaultValues() )
609  {
610  layer->removeDataDefinedProperty( "angle" );
611  }
612  else
613  {
614  if ( qgsDoubleNear( layer->angle(), symbolRotation ) )
615  {
616  layer->setDataDefinedProperty( "angle", new QgsDataDefined( dd ) );
617  }
618  else
619  {
620  QgsDataDefined* rotatedDD = rotateWholeSymbol( layer->angle() - symbolRotation, dd );
621  layer->setDataDefinedProperty( "angle", rotatedDD );
622  }
623  }
624  }
625 }
626 
628 {
629  const double symbolRotation = angle();
630  QgsDataDefined* symbolDD = 0;
631 
632  // find the base of the "en masse" pattern
633  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
634  {
635  const QgsMarkerSymbolLayerV2* layer = static_cast<const QgsMarkerSymbolLayerV2 *>( *it );
636  if ( layer->angle() == symbolRotation && layer->getDataDefinedProperty( "angle" ) )
637  {
638  symbolDD = layer->getDataDefinedProperty( "angle" );
639  break;
640  }
641  }
642 
643  if ( !symbolDD )
644  return QgsDataDefined();
645 
646  // check that all layer's angle expressions match the "en masse" pattern
647  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
648  {
649  const QgsMarkerSymbolLayerV2* layer = static_cast<const QgsMarkerSymbolLayerV2 *>( *it );
650 
651  QgsDataDefined* layerAngleDD = layer->getDataDefinedProperty( "angle" );
652 
653  if ( qgsDoubleNear( layer->angle(), symbolRotation ) )
654  {
655  if ( !layerAngleDD || *layerAngleDD != *symbolDD )
656  return QgsDataDefined();
657  }
658  else
659  {
660  QScopedPointer< QgsDataDefined > rotatedDD( rotateWholeSymbol( layer->angle() - symbolRotation, *symbolDD ) );
661  if ( !layerAngleDD || *layerAngleDD != *( rotatedDD.data() ) )
662  return QgsDataDefined();
663  }
664  }
665  return QgsDataDefined( *symbolDD );
666 }
667 
668 
670 {
671  double origSize = size();
672 
673  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
674  {
675  QgsMarkerSymbolLayerV2* layer = static_cast<QgsMarkerSymbolLayerV2*>( *it );
676  if ( layer->size() == origSize )
677  layer->setSize( s );
678  else if ( origSize != 0 )
679  {
680  // proportionally scale size
681  layer->setSize( layer->size() * s / origSize );
682  }
683  // also scale offset to maintain relative position
684  if ( origSize != 0 && ( layer->offset().x() || layer->offset().y() ) )
685  layer->setOffset( QPointF( layer->offset().x() * s / origSize,
686  layer->offset().y() * s / origSize ) );
687  }
688 }
689 
691 {
692  // return size of the largest symbol
693  double maxSize = 0;
694  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
695  {
696  const QgsMarkerSymbolLayerV2* layer = static_cast<const QgsMarkerSymbolLayerV2 *>( *it );
697  double lsize = layer->size();
698  if ( lsize > maxSize )
699  maxSize = lsize;
700  }
701  return maxSize;
702 }
703 
705 {
706  const double symbolSize = size();
707 
708  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
709  {
710  QgsMarkerSymbolLayerV2* layer = static_cast<QgsMarkerSymbolLayerV2 *>( *it );
711 
712  if ( dd.hasDefaultValues() )
713  {
714  layer->removeDataDefinedProperty( "size" );
715  layer->removeDataDefinedProperty( "offset" );
716  }
717  else
718  {
719  if ( symbolSize == 0 || qgsDoubleNear( layer->size(), symbolSize ) )
720  {
721  layer->setDataDefinedProperty( "size", new QgsDataDefined( dd ) );
722  }
723  else
724  {
725  layer->setDataDefinedProperty( "size", scaleWholeSymbol( layer->size() / symbolSize, dd ) );
726  }
727 
728  if ( layer->offset().x() || layer->offset().y() )
729  {
730  layer->setDataDefinedProperty( "offset", scaleWholeSymbol(
731  layer->offset().x() / symbolSize,
732  layer->offset().y() / symbolSize, dd ) );
733  }
734  }
735  }
736 }
737 
739 {
740  const double symbolSize = size();
741 
742  QgsDataDefined* symbolDD = 0;
743 
744  // find the base of the "en masse" pattern
745  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
746  {
747  const QgsMarkerSymbolLayerV2* layer = static_cast<const QgsMarkerSymbolLayerV2 *>( *it );
748  if ( layer->size() == symbolSize && layer->getDataDefinedProperty( "size" ) )
749  {
750  symbolDD = layer->getDataDefinedProperty( "size" );
751  break;
752  }
753  }
754 
755  if ( !symbolDD )
756  return QgsDataDefined();
757 
758  // check that all layers size expressions match the "en masse" pattern
759  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
760  {
761  const QgsMarkerSymbolLayerV2* layer = static_cast<const QgsMarkerSymbolLayerV2 *>( *it );
762 
763  QgsDataDefined* layerSizeDD = layer->getDataDefinedProperty( "size" );
764  QgsDataDefined* layerOffsetDD = layer->getDataDefinedProperty( "offset" );
765 
766  if ( qgsDoubleNear( layer->size(), symbolSize ) )
767  {
768  if ( !layerSizeDD || *layerSizeDD != *symbolDD )
769  return QgsDataDefined();
770  }
771  else
772  {
773  if ( symbolSize == 0 )
774  return QgsDataDefined();
775 
776  QScopedPointer< QgsDataDefined > scaledDD( scaleWholeSymbol( layer->size() / symbolSize, *symbolDD ) );
777  if ( !layerSizeDD || *layerSizeDD != *( scaledDD.data() ) )
778  return QgsDataDefined();
779  }
780 
781  QScopedPointer< QgsDataDefined > scaledOffsetDD( scaleWholeSymbol( layer->offset().x() / symbolSize, layer->offset().y() / symbolSize, *symbolDD ) );
782  if ( layerOffsetDD && *layerOffsetDD != *( scaledOffsetDD.data() ) )
783  return QgsDataDefined();
784  }
785 
786  return QgsDataDefined( *symbolDD );
787 }
788 
790 {
791  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
792  {
793  QgsMarkerSymbolLayerV2* layer = static_cast<QgsMarkerSymbolLayerV2*>( *it );
794  layer->setScaleMethod( scaleMethod );
795  }
796 }
797 
799 {
801 
802  if ( it == mLayers.end() )
803  return DEFAULT_SCALE_METHOD;
804 
805  // return scale method of the first symbol layer
806  const QgsMarkerSymbolLayerV2* layer = static_cast<const QgsMarkerSymbolLayerV2 *>( *it );
807  return layer->scaleMethod();
808 }
809 
810 void QgsMarkerSymbolV2::renderPointUsingLayer( QgsMarkerSymbolLayerV2* layer, const QPointF& point, QgsSymbolV2RenderContext& context )
811 {
812  static QPointF nullPoint( 0, 0 );
813 
814  QgsPaintEffect* effect = layer->paintEffect();
815  if ( effect && effect->enabled() )
816  {
817  QPainter* p = context.renderContext().painter();
818  p->save();
819  p->translate( point );
820 
821  effect->begin( context.renderContext() );
822  layer->renderPoint( nullPoint, context );
823  effect->end( context.renderContext() );
824 
825  p->restore();
826  }
827  else
828  {
829  layer->renderPoint( point, context );
830  }
831 }
832 
833 void QgsMarkerSymbolV2::renderPoint( const QPointF& point, const QgsFeature* f, QgsRenderContext& context, int layer, bool selected )
834 {
835  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, selected, mRenderHints, f, 0, mapUnitScale() );
836 
837  if ( layer != -1 )
838  {
839  if ( layer >= 0 && layer < mLayers.count() )
840  {
841  renderPointUsingLayer(( QgsMarkerSymbolLayerV2* ) mLayers[layer], point, symbolContext );
842  }
843  return;
844  }
845 
846  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
847  {
848  renderPointUsingLayer(( QgsMarkerSymbolLayerV2* ) * it, point, symbolContext );
849  }
850 }
851 
853 {
854  QgsSymbolV2* cloneSymbol = new QgsMarkerSymbolV2( cloneLayers() );
855  cloneSymbol->setAlpha( mAlpha );
856  cloneSymbol->setLayer( mLayer );
858  return cloneSymbol;
859 }
860 
861 
863 // LINE
864 
866  : QgsSymbolV2( Line, layers )
867 {
868  if ( mLayers.count() == 0 )
870 }
871 
873 {
874  double origWidth = width();
875 
876  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
877  {
878  QgsLineSymbolLayerV2* layer = ( QgsLineSymbolLayerV2* ) * it;
879  if ( layer->width() == origWidth )
880  {
881  layer->setWidth( w );
882  }
883  else if ( origWidth != 0 )
884  {
885  // proportionally scale the width
886  layer->setWidth( layer->width() * w / origWidth );
887  }
888  // also scale offset to maintain relative position
889  if ( origWidth != 0 && layer->offset() )
890  layer->setOffset( layer->offset() * w / origWidth );
891  }
892 }
893 
895 {
896  double maxWidth = 0;
897  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
898  {
899  const QgsLineSymbolLayerV2* layer = ( const QgsLineSymbolLayerV2* ) * it;
900  double width = layer->width();
901  if ( width > maxWidth )
902  maxWidth = width;
903  }
904  return maxWidth;
905 }
906 
908 {
909  const double symbolWidth = width();
910 
911  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
912  {
913  QgsLineSymbolLayerV2* layer = static_cast<QgsLineSymbolLayerV2*>( *it );
914 
915  if ( dd.hasDefaultValues() )
916  {
917  layer->removeDataDefinedProperty( "width" );
918  layer->removeDataDefinedProperty( "offset" );
919  }
920  else
921  {
922  if ( symbolWidth == 0 || qgsDoubleNear( layer->width(), symbolWidth ) )
923  {
924  layer->setDataDefinedProperty( "width", new QgsDataDefined( dd ) );
925  }
926  else
927  {
928  layer->setDataDefinedProperty( "width", scaleWholeSymbol( layer->width() / symbolWidth, dd ) );
929  }
930 
931  if ( layer->offset() )
932  {
933  layer->setDataDefinedProperty( "offset", scaleWholeSymbol( layer->offset() / symbolWidth, dd ) );
934  }
935  }
936  }
937 }
938 
940 {
941  const double symbolWidth = width();
942 
943  QgsDataDefined* symbolDD = 0;
944 
945  // find the base of the "en masse" pattern
946  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
947  {
948  const QgsLineSymbolLayerV2* layer = static_cast<const QgsLineSymbolLayerV2*>( *it );
949  if ( layer->width() == symbolWidth && layer->getDataDefinedProperty( "width" ) )
950  {
951  symbolDD = layer->getDataDefinedProperty( "width" );
952  break;
953  }
954  }
955 
956  if ( !symbolDD )
957  return QgsDataDefined();
958 
959  // check that all layers width expressions match the "en masse" pattern
960  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
961  {
962  const QgsLineSymbolLayerV2* layer = static_cast<const QgsLineSymbolLayerV2*>( *it );
963 
964  QgsDataDefined* layerWidthDD = layer->getDataDefinedProperty( "width" );
965  QgsDataDefined* layerOffsetDD = layer->getDataDefinedProperty( "offset" );
966 
967  if ( qgsDoubleNear( layer->width(), symbolWidth ) )
968  {
969  if ( !layerWidthDD || *layerWidthDD != *symbolDD )
970  return QgsDataDefined();
971  }
972  else
973  {
974  if ( symbolWidth == 0 )
975  return QgsDataDefined();
976 
977  QScopedPointer< QgsDataDefined > scaledDD( scaleWholeSymbol( layer->width() / symbolWidth, *symbolDD ) );
978  if ( !layerWidthDD || *layerWidthDD != *( scaledDD.data() ) )
979  return QgsDataDefined();
980  }
981 
982  QScopedPointer< QgsDataDefined > scaledOffsetDD( scaleWholeSymbol( layer->offset() / symbolWidth, *symbolDD ) );
983  if ( layerOffsetDD && *layerOffsetDD != *( scaledOffsetDD.data() ) )
984  return QgsDataDefined();
985  }
986 
987  return QgsDataDefined( *symbolDD );
988 }
989 
990 void QgsLineSymbolV2::renderPolyline( const QPolygonF& points, const QgsFeature* f, QgsRenderContext& context, int layer, bool selected )
991 {
992  //save old painter
993  QPainter* renderPainter = context.painter();
994  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, selected, mRenderHints, f, 0, mapUnitScale() );
995 
996  if ( layer != -1 )
997  {
998  if ( layer >= 0 && layer < mLayers.count() )
999  {
1000  renderPolylineUsingLayer(( QgsLineSymbolLayerV2* ) mLayers[layer], points, symbolContext );
1001  }
1002  return;
1003  }
1004 
1005  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
1006  {
1007  renderPolylineUsingLayer(( QgsLineSymbolLayerV2* ) * it, points, symbolContext );
1008  }
1009 
1010  context.setPainter( renderPainter );
1011 }
1012 
1013 void QgsLineSymbolV2::renderPolylineUsingLayer( QgsLineSymbolLayerV2 *layer, const QPolygonF &points, QgsSymbolV2RenderContext &context )
1014 {
1015  QgsPaintEffect* effect = layer->paintEffect();
1016  if ( effect && effect->enabled() )
1017  {
1018  QPainter* p = context.renderContext().painter();
1019  p->save();
1020  p->translate( points.boundingRect().topLeft() );
1021 
1022  effect->begin( context.renderContext() );
1023  layer->renderPolyline( points.translated( -points.boundingRect().topLeft() ), context );
1024  effect->end( context.renderContext() );
1025 
1026  p->restore();
1027  }
1028  else
1029  {
1030  layer->renderPolyline( points, context );
1031  }
1032 }
1033 
1034 
1036 {
1037  QgsSymbolV2* cloneSymbol = new QgsLineSymbolV2( cloneLayers() );
1038  cloneSymbol->setAlpha( mAlpha );
1039  cloneSymbol->setLayer( mLayer );
1041  return cloneSymbol;
1042 }
1043 
1045 // FILL
1046 
1048  : QgsSymbolV2( Fill, layers )
1049 {
1050  if ( mLayers.count() == 0 )
1052 }
1053 
1054 void QgsFillSymbolV2::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, const QgsFeature* f, QgsRenderContext& context, int layer, bool selected )
1055 {
1056  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, selected, mRenderHints, f, 0, mapUnitScale() );
1057 
1058  if ( layer != -1 )
1059  {
1060  if ( layer >= 0 && layer < mLayers.count() )
1061  {
1062  renderPolygonUsingLayer( mLayers[layer], points, rings, symbolContext );
1063  }
1064  return;
1065  }
1066 
1067  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
1068  {
1069  renderPolygonUsingLayer( *it, points, rings, symbolContext );
1070  }
1071 }
1072 
1073 void QgsFillSymbolV2::renderPolygonUsingLayer( QgsSymbolLayerV2* layer, const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context )
1074 {
1075  QgsSymbolV2::SymbolType layertype = layer->type();
1076 
1077  QgsPaintEffect* effect = layer->paintEffect();
1078  if ( effect && effect->enabled() )
1079  {
1080  QRectF bounds = polygonBounds( points, rings );
1081  QList<QPolygonF>* translatedRings = translateRings( rings, -bounds.left(), -bounds.top() );
1082 
1083  QPainter* p = context.renderContext().painter();
1084  p->save();
1085  p->translate( bounds.topLeft() );
1086 
1087  effect->begin( context.renderContext() );
1088  if ( layertype == QgsSymbolV2::Fill )
1089  {
1090  (( QgsFillSymbolLayerV2* )layer )->renderPolygon( points.translated( -bounds.topLeft() ), translatedRings, context );
1091  }
1092  else if ( layertype == QgsSymbolV2::Line )
1093  {
1094  (( QgsLineSymbolLayerV2* )layer )->renderPolygonOutline( points.translated( -bounds.topLeft() ), translatedRings, context );
1095  }
1096  delete translatedRings;
1097 
1098  effect->end( context.renderContext() );
1099  p->restore();
1100  }
1101  else
1102  {
1103  if ( layertype == QgsSymbolV2::Fill )
1104  {
1105  (( QgsFillSymbolLayerV2* )layer )->renderPolygon( points, rings, context );
1106  }
1107  else if ( layertype == QgsSymbolV2::Line )
1108  {
1109  (( QgsLineSymbolLayerV2* )layer )->renderPolygonOutline( points, rings, context );
1110  }
1111  }
1112 }
1113 
1114 QRectF QgsFillSymbolV2::polygonBounds( const QPolygonF& points, const QList<QPolygonF>* rings ) const
1115 {
1116  QRectF bounds = points.boundingRect();
1117  if ( rings )
1118  {
1120  for ( ; it != rings->constEnd(); ++it )
1121  {
1122  bounds = bounds.united(( *it ).boundingRect() );
1123  }
1124  }
1125  return bounds;
1126 }
1127 
1128 QList<QPolygonF>* QgsFillSymbolV2::translateRings( const QList<QPolygonF>* rings, double dx, double dy ) const
1129 {
1130  if ( !rings )
1131  return 0;
1132 
1133  QList<QPolygonF>* translatedRings = new QList<QPolygonF>;
1135  for ( ; it != rings->constEnd(); ++it )
1136  {
1137  translatedRings->append(( *it ).translated( dx, dy ) );
1138  }
1139  return translatedRings;
1140 }
1141 
1143 {
1144  QgsSymbolV2* cloneSymbol = new QgsFillSymbolV2( cloneLayers() );
1145  cloneSymbol->setAlpha( mAlpha );
1146  cloneSymbol->setLayer( mLayer );
1148  return cloneSymbol;
1149 }
1150 
1152 {
1153  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
1154  {
1155  QgsFillSymbolLayerV2* layer = ( QgsFillSymbolLayerV2* ) * it;
1156  layer->setAngle( angle );
1157  }
1158 }
1159 
1160 
void setForceVectorOutput(bool force)
void setLocked(bool locked)
bool deleteSymbolLayer(int index)
delete symbol layer at specified index
QgsSymbolV2RenderContext(QgsRenderContext &c, QgsSymbolV2::OutputUnit u, qreal alpha=1.0, bool selected=false, int renderHints=0, const QgsFeature *f=0, const QgsFields *fields=0, const QgsMapUnitScale &mapUnitScale=QgsMapUnitScale())
static unsigned index
void setViewBox(const QRect &viewBox)
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's extent...
Definition: qgssymbolv2.h:193
QgsSymbolV2(SymbolType type, QgsSymbolLayerV2List layers)
Definition: qgssymbolv2.cpp:77
int width() const
bool mClipFeaturesToExtent
Definition: qgssymbolv2.h:227
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()
void setSize(const QSize &size)
virtual double width() const
void setRenderHint(RenderHint hint, bool on)
const QgsVectorLayer * mLayer
Definition: qgssymbolv2.h:229
SymbolType type() const
Definition: qgssymbolv2.h:86
QSet< QString > usedAttributes() const
QString field() const
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
void setDataDefinedSize(const QgsDataDefined &dd)
Set data defined size for whole symbol (including all symbol layers).
bool save(const QString &fileName, const char *format, int quality) const
static QString encodeSldUom(QgsSymbolV2::OutputUnit unit, double *scaleFactor)
void setScaleMethod(QgsSymbolV2::ScaleMethod scaleMethod)
double size() const
QgsFillSymbolV2(QgsSymbolLayerV2List layers=QgsSymbolLayerV2List())
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. ...
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
ScaleMethod scaleMethod()
void save()
QgsMapUnitScale mapUnitScale() const
Container of fields for a vector layer.
Definition: qgsfield.h:173
qreal top() const
QgsSymbolV2 * symbol(QString name)
return a NEW copy of symbol
Definition: qgsstylev2.cpp:166
QString expressionString() const
T takeAt(int i)
GeometryType
Definition: qgis.h:155
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:162
void drawLine(const QLineF &line)
SymbolType mType
Definition: qgssymbolv2.h:220
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
virtual void removeDataDefinedProperty(const QString &property)
Removes a data defined property from the layer.
qreal left() const
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Definition: qgis.h:350
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:52
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:209
virtual void startRender(QgsSymbolV2RenderContext &context)=0
static QString encodeColor(QColor color)
QColor fromHsv(int h, int s, int v, int a)
void setUseExpression(bool use)
void setColor(const QColor &color)
static QgsRenderContext createRenderContext(QPainter *p)
Creates a render context for a pixel based device.
QString number(int n, int base)
QgsSymbolLayerV2List mLayers
Definition: qgssymbolv2.h:221
int count(const T &value) const
qreal x() const
qreal y() const
void append(const T &value)
double width() const
QgsSymbolLayerV2List cloneLayers() const
void setOffset(double offset)
bool appendSymbolLayer(QgsSymbolLayerV2 *layer)
Append symbol layer at the end of the list Ownership will be transferred.
bool empty() const
virtual void renderPoint(const QPointF &point, QgsSymbolV2RenderContext &context)=0
void fill(uint pixelValue)
QgsLineSymbolV2(QgsSymbolLayerV2List layers=QgsSymbolLayerV2List())
void setLineAngle(double lineAngle)
Sets the line angle modification for the symbol's angle.
void startRender(QgsRenderContext &context, const QgsFields *fields=0)
qreal alpha() const
Get alpha transparency 1 for opaque, 0 for invisible.
Definition: qgssymbolv2.h:178
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())
void setPen(const QColor &color)
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:208
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)
void setAngle(double angle)
double angle() const
void setAngle(double angle)
virtual QgsSymbolV2 * clone() const override
void setPainter(QPainter *p)
void setSize(double size)
qreal mAlpha
Symbol opacity (in the range 0 - 1)
Definition: qgssymbolv2.h:224
QgsSymbolV2RenderContext & operator=(const QgsSymbolV2RenderContext &)
QRectF united(const QRectF &rectangle) const
virtual void renderPolygonOutline(const QPolygonF &points, QList< QPolygonF > *rings, QgsSymbolV2RenderContext &context)
QgsDataDefined * rotateWholeSymbol(double additionalRotation, const QgsDataDefined &dd)
Definition: qgssymbolv2.cpp:42
void renderPoint(const QPointF &point, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
void setLineAngle(double lineAngle)
Sets the line angle modification for the symbol's angle.
QgsSymbolV2::ScaleMethod scaleMethod() const
QgsSymbolV2::SymbolType type() const
bool useExpression() const
T * data() const
virtual QgsSymbolV2 * clone() const override
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
void setFileName(const QString &fileName)
void exportImage(QString path, QString format, QSize size)
export symbol as image format. PNG and SVG supported
void restore()
bool isSymbolLayerCompatible(SymbolType t)
check whether a symbol layer type can be used within the symbol (marker-marker, line-line, fill-fill/line)
void setDataDefinedWidth(const QgsDataDefined &dd)
Set data defined width for whole symbol (including all symbol layers).
QgsMarkerSymbolV2(QgsSymbolLayerV2List layers=QgsSymbolLayerV2List())
Contains information about the context of a rendering operation.
QString readEntry(const QString &scope, const QString &key, const QString &def=QString::null, bool *ok=0) const
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.
static double lineWidthScaleFactor(const QgsRenderContext &c, QgsSymbolV2::OutputUnit u, const QgsMapUnitScale &scale=QgsMapUnitScale())
Returns the line width scale factor depending on the unit and the paint device.
QSet< T > & unite(const QSet< T > &other)
static QgsSymbolV2 * defaultSymbol(QGis::GeometryType geomType)
return new default symbol for specified geometry type
void insert(int i, const T &value)
double offset() const
QgsRenderContext & renderContext()
Definition: qgssymbolv2.h:241
virtual QgsDataDefined * getDataDefinedProperty(const QString &property) const
Returns the data defined property corresponding to the specified property key.
static QgsProject * instance()
access to canonical QgsProject instance
Definition: qgsproject.cpp:351
int height() const
QgsSymbolV2::OutputUnit outputUnit() const
void translate(const QPointF &offset)
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.
QImage asImage(QSize size, QgsRenderContext *customContext=0)
Generate symbol as image.
const_iterator constEnd() const
QString dump() const
const_iterator constBegin() const
void drawPreviewIcon(QPainter *painter, QSize size, QgsRenderContext *customContext=0)
Draw icon of the symbol that occupyies area given by size using the painter.
void setSize(double size)
void setAngle(double angle)
QPointF offset() const
virtual QgsSymbolV2 * clone() const override
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
virtual void stopRender(QgsSymbolV2RenderContext &context)=0
void setExpressionString(const QString &expr)
void setOutputUnit(QgsSymbolV2::OutputUnit u)
void setAlpha(qreal alpha)
Set alpha transparency 1 for opaque, 0 for invisible.
Definition: qgssymbolv2.h:180
iterator begin()
QImage bigSymbolPreviewImage()
void setScaleMethod(QgsSymbolV2::ScaleMethod scaleMethod)
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
virtual void begin(QgsRenderContext &context)
Begins intercepting paint operations to a render context.
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the layer.
QColor color() const
int mRenderHints
Definition: qgssymbolv2.h:226
virtual Q_DECL_DEPRECATED void setDataDefinedProperty(const QString &property, const QString &expressionString)
Sets a data defined expression for a property.