QGIS API Documentation  2.11.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 
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 
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 {
155  for ( ; it != mLayers.end(); ++it )
156  {
157  ( *it )->setOutputUnit( u );
158  }
159 }
160 
162 {
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
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 
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 
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 
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 
456 {
457  QSet<QString> attributes;
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 
489 double QgsSymbolV2RenderContext::outputPixelSize( double size ) const
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 )
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 {
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 || *layerAngleDD != *symbolDD )
635  return QgsDataDefined();
636  }
637  else
638  {
639  QScopedPointer< QgsDataDefined > rotatedDD( rotateWholeSymbol( layer->angle() - symbolRotation, *symbolDD ) );
640  if ( !layerAngleDD || *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  QScopedPointer< QgsDataDefined > scaledOffsetDD( scaleWholeSymbol( layer->offset().x() / symbolSize, layer->offset().y() / symbolSize, *symbolDD ) );
761  if ( layerOffsetDD && *layerOffsetDD != *( scaledOffsetDD.data() ) )
762  return QgsDataDefined();
763  }
764 
765  return QgsDataDefined( *symbolDD );
766 }
767 
769 {
770  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
771  {
772  QgsMarkerSymbolLayerV2* layer = static_cast<QgsMarkerSymbolLayerV2*>( *it );
773  layer->setScaleMethod( scaleMethod );
774  }
775 }
776 
778 {
780 
781  if ( it == mLayers.end() )
782  return DEFAULT_SCALE_METHOD;
783 
784  // return scale method of the first symbol layer
785  const QgsMarkerSymbolLayerV2* layer = static_cast<const QgsMarkerSymbolLayerV2 *>( *it );
786  return layer->scaleMethod();
787 }
788 
789 void QgsMarkerSymbolV2::renderPointUsingLayer( QgsMarkerSymbolLayerV2* layer, const QPointF& point, QgsSymbolV2RenderContext& context )
790 {
791  static QPointF nullPoint( 0, 0 );
792 
793  QgsPaintEffect* effect = layer->paintEffect();
794  if ( effect && effect->enabled() )
795  {
796  QPainter* p = context.renderContext().painter();
797  p->save();
798  p->translate( point );
799 
800  effect->begin( context.renderContext() );
801  layer->renderPoint( nullPoint, context );
802  effect->end( context.renderContext() );
803 
804  p->restore();
805  }
806  else
807  {
808  layer->renderPoint( point, context );
809  }
810 }
811 
812 void QgsMarkerSymbolV2::renderPoint( const QPointF& point, const QgsFeature* f, QgsRenderContext& context, int layer, bool selected )
813 {
814  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, selected, mRenderHints, f, 0, mapUnitScale() );
815 
816  if ( layer != -1 )
817  {
818  if ( layer >= 0 && layer < mLayers.count() )
819  {
820  renderPointUsingLayer(( QgsMarkerSymbolLayerV2* ) mLayers[layer], point, symbolContext );
821  }
822  return;
823  }
824 
825  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
826  {
827  renderPointUsingLayer(( QgsMarkerSymbolLayerV2* ) * it, point, symbolContext );
828  }
829 }
830 
832 {
833  QgsSymbolV2* cloneSymbol = new QgsMarkerSymbolV2( cloneLayers() );
834  cloneSymbol->setAlpha( mAlpha );
835  cloneSymbol->setLayer( mLayer );
837  return cloneSymbol;
838 }
839 
840 
842 // LINE
843 
845  : QgsSymbolV2( Line, layers )
846 {
847  if ( mLayers.count() == 0 )
849 }
850 
852 {
853  double origWidth = width();
854 
855  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
856  {
857  QgsLineSymbolLayerV2* layer = ( QgsLineSymbolLayerV2* ) * it;
858  if ( layer->width() == origWidth )
859  {
860  layer->setWidth( w );
861  }
862  else if ( origWidth != 0 )
863  {
864  // proportionally scale the width
865  layer->setWidth( layer->width() * w / origWidth );
866  }
867  // also scale offset to maintain relative position
868  if ( origWidth != 0 && layer->offset() )
869  layer->setOffset( layer->offset() * w / origWidth );
870  }
871 }
872 
874 {
875  double maxWidth = 0;
876  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
877  {
878  const QgsLineSymbolLayerV2* layer = ( const QgsLineSymbolLayerV2* ) * it;
879  double width = layer->width();
880  if ( width > maxWidth )
881  maxWidth = width;
882  }
883  return maxWidth;
884 }
885 
887 {
888  const double symbolWidth = width();
889 
890  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
891  {
892  QgsLineSymbolLayerV2* layer = static_cast<QgsLineSymbolLayerV2*>( *it );
893 
894  if ( dd.hasDefaultValues() )
895  {
896  layer->removeDataDefinedProperty( "width" );
897  layer->removeDataDefinedProperty( "offset" );
898  }
899  else
900  {
901  if ( symbolWidth == 0 || qgsDoubleNear( layer->width(), symbolWidth ) )
902  {
903  layer->setDataDefinedProperty( "width", new QgsDataDefined( dd ) );
904  }
905  else
906  {
907  layer->setDataDefinedProperty( "width", scaleWholeSymbol( layer->width() / symbolWidth, dd ) );
908  }
909 
910  if ( layer->offset() )
911  {
912  layer->setDataDefinedProperty( "offset", scaleWholeSymbol( layer->offset() / symbolWidth, dd ) );
913  }
914  }
915  }
916 }
917 
919 {
920  const double symbolWidth = width();
921 
922  QgsDataDefined* symbolDD = 0;
923 
924  // find the base of the "en masse" pattern
925  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
926  {
927  const QgsLineSymbolLayerV2* layer = static_cast<const QgsLineSymbolLayerV2*>( *it );
928  if ( layer->width() == symbolWidth && layer->getDataDefinedProperty( "width" ) )
929  {
930  symbolDD = layer->getDataDefinedProperty( "width" );
931  break;
932  }
933  }
934 
935  if ( !symbolDD )
936  return QgsDataDefined();
937 
938  // check that all layers width expressions match the "en masse" pattern
939  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
940  {
941  const QgsLineSymbolLayerV2* layer = static_cast<const QgsLineSymbolLayerV2*>( *it );
942 
943  QgsDataDefined* layerWidthDD = layer->getDataDefinedProperty( "width" );
944  QgsDataDefined* layerOffsetDD = layer->getDataDefinedProperty( "offset" );
945 
946  if ( qgsDoubleNear( layer->width(), symbolWidth ) )
947  {
948  if ( !layerWidthDD || *layerWidthDD != *symbolDD )
949  return QgsDataDefined();
950  }
951  else
952  {
953  if ( symbolWidth == 0 )
954  return QgsDataDefined();
955 
956  QScopedPointer< QgsDataDefined > scaledDD( scaleWholeSymbol( layer->width() / symbolWidth, *symbolDD ) );
957  if ( !layerWidthDD || *layerWidthDD != *( scaledDD.data() ) )
958  return QgsDataDefined();
959  }
960 
961  QScopedPointer< QgsDataDefined > scaledOffsetDD( scaleWholeSymbol( layer->offset() / symbolWidth, *symbolDD ) );
962  if ( layerOffsetDD && *layerOffsetDD != *( scaledOffsetDD.data() ) )
963  return QgsDataDefined();
964  }
965 
966  return QgsDataDefined( *symbolDD );
967 }
968 
969 void QgsLineSymbolV2::renderPolyline( const QPolygonF& points, const QgsFeature* f, QgsRenderContext& context, int layer, bool selected )
970 {
971  //save old painter
972  QPainter* renderPainter = context.painter();
973  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, selected, mRenderHints, f, 0, mapUnitScale() );
974 
975  if ( layer != -1 )
976  {
977  if ( layer >= 0 && layer < mLayers.count() )
978  {
979  renderPolylineUsingLayer(( QgsLineSymbolLayerV2* ) mLayers[layer], points, symbolContext );
980  }
981  return;
982  }
983 
984  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
985  {
986  renderPolylineUsingLayer(( QgsLineSymbolLayerV2* ) * it, points, symbolContext );
987  }
988 
989  context.setPainter( renderPainter );
990 }
991 
992 void QgsLineSymbolV2::renderPolylineUsingLayer( QgsLineSymbolLayerV2 *layer, const QPolygonF &points, QgsSymbolV2RenderContext &context )
993 {
994  QgsPaintEffect* effect = layer->paintEffect();
995  if ( effect && effect->enabled() )
996  {
997  QPainter* p = context.renderContext().painter();
998  p->save();
999  p->translate( points.boundingRect().topLeft() );
1000 
1001  effect->begin( context.renderContext() );
1002  layer->renderPolyline( points.translated( -points.boundingRect().topLeft() ), context );
1003  effect->end( context.renderContext() );
1004 
1005  p->restore();
1006  }
1007  else
1008  {
1009  layer->renderPolyline( points, context );
1010  }
1011 }
1012 
1013 
1015 {
1016  QgsSymbolV2* cloneSymbol = new QgsLineSymbolV2( cloneLayers() );
1017  cloneSymbol->setAlpha( mAlpha );
1018  cloneSymbol->setLayer( mLayer );
1020  return cloneSymbol;
1021 }
1022 
1024 // FILL
1025 
1027  : QgsSymbolV2( Fill, layers )
1028 {
1029  if ( mLayers.count() == 0 )
1031 }
1032 
1033 void QgsFillSymbolV2::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, const QgsFeature* f, QgsRenderContext& context, int layer, bool selected )
1034 {
1035  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, selected, mRenderHints, f, 0, mapUnitScale() );
1036 
1037  if ( layer != -1 )
1038  {
1039  if ( layer >= 0 && layer < mLayers.count() )
1040  {
1041  renderPolygonUsingLayer( mLayers[layer], points, rings, symbolContext );
1042  }
1043  return;
1044  }
1045 
1046  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
1047  {
1048  renderPolygonUsingLayer( *it, points, rings, symbolContext );
1049  }
1050 }
1051 
1052 void QgsFillSymbolV2::renderPolygonUsingLayer( QgsSymbolLayerV2* layer, const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context )
1053 {
1054  QgsSymbolV2::SymbolType layertype = layer->type();
1055 
1056  QgsPaintEffect* effect = layer->paintEffect();
1057  if ( effect && effect->enabled() )
1058  {
1059  QRectF bounds = polygonBounds( points, rings );
1060  QList<QPolygonF>* translatedRings = translateRings( rings, -bounds.left(), -bounds.top() );
1061 
1062  QPainter* p = context.renderContext().painter();
1063  p->save();
1064  p->translate( bounds.topLeft() );
1065 
1066  effect->begin( context.renderContext() );
1067  if ( layertype == QgsSymbolV2::Fill )
1068  {
1069  (( QgsFillSymbolLayerV2* )layer )->renderPolygon( points.translated( -bounds.topLeft() ), translatedRings, context );
1070  }
1071  else if ( layertype == QgsSymbolV2::Line )
1072  {
1073  (( QgsLineSymbolLayerV2* )layer )->renderPolygonOutline( points.translated( -bounds.topLeft() ), translatedRings, context );
1074  }
1075  delete translatedRings;
1076 
1077  effect->end( context.renderContext() );
1078  p->restore();
1079  }
1080  else
1081  {
1082  if ( layertype == QgsSymbolV2::Fill )
1083  {
1084  (( QgsFillSymbolLayerV2* )layer )->renderPolygon( points, rings, context );
1085  }
1086  else if ( layertype == QgsSymbolV2::Line )
1087  {
1088  (( QgsLineSymbolLayerV2* )layer )->renderPolygonOutline( points, rings, context );
1089  }
1090  }
1091 }
1092 
1093 QRectF QgsFillSymbolV2::polygonBounds( const QPolygonF& points, const QList<QPolygonF>* rings ) const
1094 {
1095  QRectF bounds = points.boundingRect();
1096  if ( rings )
1097  {
1099  for ( ; it != rings->constEnd(); ++it )
1100  {
1101  bounds = bounds.united(( *it ).boundingRect() );
1102  }
1103  }
1104  return bounds;
1105 }
1106 
1107 QList<QPolygonF>* QgsFillSymbolV2::translateRings( const QList<QPolygonF>* rings, double dx, double dy ) const
1108 {
1109  if ( !rings )
1110  return 0;
1111 
1112  QList<QPolygonF>* translatedRings = new QList<QPolygonF>;
1114  for ( ; it != rings->constEnd(); ++it )
1115  {
1116  translatedRings->append(( *it ).translated( dx, dy ) );
1117  }
1118  return translatedRings;
1119 }
1120 
1122 {
1123  QgsSymbolV2* cloneSymbol = new QgsFillSymbolV2( cloneLayers() );
1124  cloneSymbol->setAlpha( mAlpha );
1125  cloneSymbol->setLayer( mLayer );
1127  return cloneSymbol;
1128 }
1129 
1131 {
1132  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
1133  {
1134  QgsFillSymbolLayerV2* layer = ( QgsFillSymbolLayerV2* ) * it;
1135  layer->setAngle( angle );
1136  }
1137 }
1138 
1139 
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
int width() const
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
void setRenderHint(RenderHint hint, bool on)
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)
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:119
void drawLine(const QLineF &line)
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.
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: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)
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:201
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
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: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 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:188
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:204
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: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
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()
virtual ~QgsSymbolV2()
virtual void renderPolyline(const QPolygonF &points, QgsSymbolV2RenderContext &context)=0
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
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: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
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)
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:160
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:206
virtual Q_DECL_DEPRECATED void setDataDefinedProperty(const QString &property, const QString &expressionString)
Sets a data defined expression for a property.