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