QGIS API Documentation  2.9.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator 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 <QColor>
32 #include <QImage>
33 #include <QPainter>
34 #include <QSize>
35 
36 #include <cmath>
37 
39  : mType( type )
40  , mLayers( layers )
41  , mAlpha( 1.0 )
42  , mRenderHints( 0 )
43  , mClipFeaturesToExtent( true )
44  , mLayer( 0 )
45 {
46 
47  // check they're all correct symbol layers
48  for ( int i = 0; i < mLayers.count(); i++ )
49  {
50  if ( mLayers[i] == NULL )
51  {
52  mLayers.removeAt( i-- );
53  }
54  else if ( !isSymbolLayerCompatible( mLayers[i]->type() ) )
55  {
56  delete mLayers[i];
57  mLayers.removeAt( i-- );
58  }
59  }
60 }
61 
63 {
64  // delete all symbol layers (we own them, so it's okay)
65  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
66  delete *it;
67 }
68 
70 {
71  if ( mLayers.empty() )
72  {
73  return QgsSymbolV2::Mixed;
74  }
75 
76  QgsSymbolLayerV2List::const_iterator it = mLayers.constBegin();
77 
78  QgsSymbolV2::OutputUnit unit = ( *it )->outputUnit();
79 
80  for ( ; it != mLayers.constEnd(); ++it )
81  {
82  if (( *it )->outputUnit() != unit )
83  {
84  return QgsSymbolV2::Mixed;
85  }
86  }
87  return unit;
88 }
89 
91 {
92  if ( mLayers.empty() )
93  {
94  return QgsMapUnitScale();
95  }
96 
97  QgsSymbolLayerV2List::const_iterator it = mLayers.constBegin();
98  if ( it == mLayers.constEnd() )
99  return QgsMapUnitScale();
100 
101  QgsMapUnitScale scale = ( *it )->mapUnitScale();
102  ++it;
103 
104  for ( ; it != mLayers.constEnd(); ++it )
105  {
106  if (( *it )->mapUnitScale() != scale )
107  {
108  return QgsMapUnitScale();
109  }
110  }
111  return scale;
112 }
113 
115 {
116  QgsSymbolLayerV2List::iterator it = mLayers.begin();
117  for ( ; it != mLayers.end(); ++it )
118  {
119  ( *it )->setOutputUnit( u );
120  }
121 }
122 
124 {
125  QgsSymbolLayerV2List::iterator it = mLayers.begin();
126  for ( ; it != mLayers.end(); ++it )
127  {
128  ( *it )->setMapUnitScale( scale );
129  }
130 }
131 
133 {
134  QgsSymbolV2* s = 0;
135 
136  // override global default if project has a default for this type
137  QString defaultSymbol;
138  switch ( geomType )
139  {
140  case QGis::Point :
141  defaultSymbol = QgsProject::instance()->readEntry( "DefaultStyles", "/Marker", "" );
142  break;
143  case QGis::Line :
144  defaultSymbol = QgsProject::instance()->readEntry( "DefaultStyles", "/Line", "" );
145  break;
146  case QGis::Polygon :
147  defaultSymbol = QgsProject::instance()->readEntry( "DefaultStyles", "/Fill", "" );
148  break;
149  default: defaultSymbol = ""; break;
150  }
151  if ( defaultSymbol != "" )
152  s = QgsStyleV2::defaultStyle()->symbol( defaultSymbol );
153 
154  // if no default found for this type, get global default (as previously)
155  if ( ! s )
156  {
157  switch ( geomType )
158  {
159  case QGis::Point: s = new QgsMarkerSymbolV2(); break;
160  case QGis::Line: s = new QgsLineSymbolV2(); break;
161  case QGis::Polygon: s = new QgsFillSymbolV2(); break;
162  default: QgsDebugMsg( "unknown layer's geometry type" ); return NULL;
163  }
164  }
165 
166  // set alpha transparency
167  s->setAlpha( QgsProject::instance()->readDoubleEntry( "DefaultStyles", "/AlphaInt", 255 ) / 255.0 );
168 
169  // set random color, it project prefs allow
170  if ( defaultSymbol == "" ||
171  QgsProject::instance()->readBoolEntry( "DefaultStyles", "/RandomColors", true ) )
172  {
173  s->setColor( QColor::fromHsv( qrand() % 360, 64 + qrand() % 192, 128 + qrand() % 128 ) );
174  }
175 
176  return s;
177 }
178 
180 {
181  if ( layer < 0 || layer >= mLayers.count() )
182  return NULL;
183 
184  return mLayers[layer];
185 }
186 
187 
189 {
190  // fill symbol can contain also line symbol layers for drawing of outlines
191  if ( mType == Fill && t == Line )
192  return true;
193 
194  return mType == t;
195 }
196 
197 
199 {
200  if ( index < 0 || index > mLayers.count() ) // can be added also after the last index
201  return false;
202  if ( layer == NULL || !isSymbolLayerCompatible( layer->type() ) )
203  return false;
204 
205  mLayers.insert( index, layer );
206  return true;
207 }
208 
209 
211 {
212  if ( layer == NULL || !isSymbolLayerCompatible( layer->type() ) )
213  return false;
214 
215  mLayers.append( layer );
216  return true;
217 }
218 
219 
221 {
222  if ( index < 0 || index >= mLayers.count() )
223  return false;
224 
225  delete mLayers[index];
226  mLayers.removeAt( index );
227  return true;
228 }
229 
230 
232 {
233  if ( index < 0 || index >= mLayers.count() )
234  return NULL;
235 
236  return mLayers.takeAt( index );
237 }
238 
239 
241 {
242  if ( index < 0 || index >= mLayers.count() )
243  return false;
244  if ( layer == NULL || !isSymbolLayerCompatible( layer->type() ) )
245  return false;
246 
247  delete mLayers[index]; // first delete the original layer
248  mLayers[index] = layer; // set new layer
249  return true;
250 }
251 
252 
253 void QgsSymbolV2::startRender( QgsRenderContext& context, const QgsFields* fields )
254 {
255  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, false, mRenderHints, 0, fields, mapUnitScale() );
256 
257 
258  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
259  ( *it )->startRender( symbolContext );
260 }
261 
263 {
264  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, false, mRenderHints, 0, 0, mapUnitScale() );
265 
266  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
267  ( *it )->stopRender( symbolContext );
268 
269  mLayer = NULL;
270 }
271 
272 void QgsSymbolV2::setColor( const QColor& color )
273 {
274  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
275  {
276  if ( !( *it )->isLocked() )
277  ( *it )->setColor( color );
278  }
279 }
280 
281 QColor QgsSymbolV2::color() const
282 {
283  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
284  {
285  // return color of the first unlocked layer
286  if ( !( *it )->isLocked() )
287  return ( *it )->color();
288  }
289  return QColor( 0, 0, 0 );
290 }
291 
292 void QgsSymbolV2::drawPreviewIcon( QPainter* painter, QSize size, QgsRenderContext* customContext )
293 {
294  QgsRenderContext context = customContext ? *customContext : QgsSymbolLayerV2Utils::createRenderContext( painter );
295  context.setForceVectorOutput( true );
296  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, false, mRenderHints, 0, 0, mapUnitScale() );
297 
298  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
299  {
300  if ( mType == Fill && ( *it )->type() == Line )
301  {
302  // line symbol layer would normally draw just a line
303  // so we override this case to force it to draw a polygon outline
305 
306  // from QgsFillSymbolLayerV2::drawPreviewIcon()
307  QPolygonF poly = QRectF( QPointF( 0, 0 ), QPointF( size.width() - 1, size.height() - 1 ) );
308  lsl->startRender( symbolContext );
309  lsl->renderPolygonOutline( poly, NULL, symbolContext );
310  lsl->stopRender( symbolContext );
311  }
312  else
313  ( *it )->drawPreviewIcon( symbolContext, size );
314  }
315 }
316 
317 QImage QgsSymbolV2::asImage( QSize size, QgsRenderContext* customContext )
318 {
319  QImage image( size, QImage::Format_ARGB32_Premultiplied );
320  image.fill( 0 );
321 
322  QPainter p( &image );
323  p.setRenderHint( QPainter::Antialiasing );
324 
325  drawPreviewIcon( &p, size, customContext );
326 
327  return image;
328 }
329 
330 
332 {
333  QImage preview( QSize( 100, 100 ), QImage::Format_ARGB32_Premultiplied );
334  preview.fill( 0 );
335 
336  QPainter p( &preview );
337  p.setRenderHint( QPainter::Antialiasing );
338  p.translate( 0.5, 0.5 ); // shift by half a pixel to avoid blurring due antialising
339 
340  if ( mType == QgsSymbolV2::Marker )
341  {
342  p.setPen( QPen( Qt::gray ) );
343  p.drawLine( 0, 50, 100, 50 );
344  p.drawLine( 50, 0, 50, 100 );
345  }
346 
348  startRender( context );
349 
350  if ( mType == QgsSymbolV2::Line )
351  {
352  QPolygonF poly;
353  poly << QPointF( 0, 50 ) << QPointF( 99, 50 );
354  static_cast<QgsLineSymbolV2*>( this )->renderPolyline( poly, 0, context );
355  }
356  else if ( mType == QgsSymbolV2::Fill )
357  {
358  QPolygonF polygon;
359  polygon << QPointF( 20, 20 ) << QPointF( 80, 20 ) << QPointF( 80, 80 ) << QPointF( 20, 80 ) << QPointF( 20, 20 );
360  static_cast<QgsFillSymbolV2*>( this )->renderPolygon( polygon, NULL, 0, context );
361  }
362  else // marker
363  {
364  static_cast<QgsMarkerSymbolV2*>( this )->renderPoint( QPointF( 50, 50 ), 0, context );
365  }
366 
367  stopRender( context );
368  return preview;
369 }
370 
371 
372 QString QgsSymbolV2::dump() const
373 {
374  QString t;
375  switch ( type() )
376  {
377  case QgsSymbolV2::Marker: t = "MARKER"; break;
378  case QgsSymbolV2::Line: t = "LINE"; break;
379  case QgsSymbolV2::Fill: t = "FILL"; break;
380  default: Q_ASSERT( 0 && "unknown symbol type" );
381  }
382  QString s = QString( "%1 SYMBOL (%2 layers) color %3" ).arg( t ).arg( mLayers.count() ).arg( QgsSymbolLayerV2Utils::encodeColor( color() ) );
383 
384  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
385  {
386  // TODO:
387  }
388  return s;
389 }
390 
391 void QgsSymbolV2::toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const
392 {
393  props[ "alpha" ] = QString::number( alpha() );
394  double scaleFactor = 1.0;
395  props[ "uom" ] = QgsSymbolLayerV2Utils::encodeSldUom( outputUnit(), &scaleFactor );
396  props[ "uomScale" ] = scaleFactor != 1 ? QString::number( scaleFactor ) : "";
397 
398  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
399  {
400  ( *it )->toSld( doc, element, props );
401  }
402 }
403 
405 {
407  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
408  {
409  QgsSymbolLayerV2* layer = ( *it )->clone();
410  layer->setLocked(( *it )->isLocked() );
411  layer->setRenderingPass(( *it )->renderingPass() );
412  lst.append( layer );
413  }
414  return lst;
415 }
416 
417 QSet<QString> QgsSymbolV2::usedAttributes() const
418 {
419  QSet<QString> attributes;
420  QgsSymbolLayerV2List::const_iterator sIt = mLayers.constBegin();
421  for ( ; sIt != mLayers.constEnd(); ++sIt )
422  {
423  if ( *sIt )
424  {
425  attributes.unite(( *sIt )->usedAttributes() );
426  }
427  }
428  return attributes;
429 }
430 
432 
433 
434 QgsSymbolV2RenderContext::QgsSymbolV2RenderContext( QgsRenderContext& c, QgsSymbolV2::OutputUnit u, qreal alpha, bool selected, int renderHints, const QgsFeature* f, const QgsFields* fields, const QgsMapUnitScale& mapUnitScale )
435  : mRenderContext( c ), mOutputUnit( u ), mMapUnitScale( mapUnitScale ), mAlpha( alpha ), mSelected( selected ), mRenderHints( renderHints ), mFeature( f ), mFields( fields )
436 {
437 
438 }
439 
441 {
442 
443 }
444 
445 
446 double QgsSymbolV2RenderContext::outputLineWidth( double width ) const
447 {
448  return width * QgsSymbolLayerV2Utils::lineWidthScaleFactor( mRenderContext, mOutputUnit, mMapUnitScale );
449 }
450 
452 {
453  return size * QgsSymbolLayerV2Utils::pixelSizeScaleFactor( mRenderContext, mOutputUnit, mMapUnitScale );
454 }
455 
457 {
458  // This is just a dummy implementation of assignment.
459  // sip 4.7 generates a piece of code that needs this function to exist.
460  // It's not generated automatically by the compiler because of
461  // mRenderContext member which is a reference (and thus can't be changed).
462  Q_ASSERT( false );
463  return *this;
464 }
465 
467 
469 {
471  if ( sl == NULL )
472  return NULL;
473 
474  QgsSymbolLayerV2List layers;
475  layers.append( sl );
476  return new QgsMarkerSymbolV2( layers );
477 }
478 
480 {
482  if ( sl == NULL )
483  return NULL;
484 
485  QgsSymbolLayerV2List layers;
486  layers.append( sl );
487  return new QgsLineSymbolV2( layers );
488 }
489 
491 {
493  if ( sl == NULL )
494  return NULL;
495 
496  QgsSymbolLayerV2List layers;
497  layers.append( sl );
498  return new QgsFillSymbolV2( layers );
499 }
500 
502 
503 
505  : QgsSymbolV2( Marker, layers )
506 {
507  if ( mLayers.count() == 0 )
508  mLayers.append( new QgsSimpleMarkerSymbolLayerV2() );
509 }
510 
511 void QgsMarkerSymbolV2::setAngle( double ang )
512 {
513  double origAngle = angle();
514  double angleDiff = ang - origAngle;
515  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
516  {
518  layer->setAngle( layer->angle() + angleDiff );
519  }
520 }
521 
523 {
524  QgsSymbolLayerV2List::const_iterator it = mLayers.begin();
525 
526  if ( it == mLayers.end() )
527  return 0;
528 
529  // return angle of the first symbol layer
530  const QgsMarkerSymbolLayerV2* layer = static_cast<const QgsMarkerSymbolLayerV2 *>( *it );
531  return layer->angle();
532 }
533 
535 {
536  double origSize = size();
537 
538  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
539  {
540  QgsMarkerSymbolLayerV2* layer = static_cast<QgsMarkerSymbolLayerV2*>( *it );
541  if ( layer->size() == origSize )
542  layer->setSize( s );
543  else
544  {
545  // proportionally scale size
546  if ( origSize != 0 )
547  layer->setSize( layer->size() * s / origSize );
548  }
549  }
550 }
551 
553 {
554  // return size of the largest symbol
555  double maxSize = 0;
556  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
557  {
558  const QgsMarkerSymbolLayerV2* layer = static_cast<const QgsMarkerSymbolLayerV2 *>( *it );
559  double lsize = layer->size();
560  if ( lsize > maxSize )
561  maxSize = lsize;
562  }
563  return maxSize;
564 }
565 
566 
568 {
569  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
570  {
571  QgsMarkerSymbolLayerV2* layer = static_cast<QgsMarkerSymbolLayerV2*>( *it );
572  layer->setScaleMethod( scaleMethod );
573  }
574 }
575 
577 {
578  QgsSymbolLayerV2List::const_iterator it = mLayers.begin();
579 
580  if ( it == mLayers.end() )
581  return DEFAULT_SCALE_METHOD;
582 
583  // return scale method of the first symbol layer
584  const QgsMarkerSymbolLayerV2* layer = static_cast<const QgsMarkerSymbolLayerV2 *>( *it );
585  return layer->scaleMethod();
586 }
587 
588 void QgsMarkerSymbolV2::renderPointUsingLayer( QgsMarkerSymbolLayerV2* layer, const QPointF& point, QgsSymbolV2RenderContext& context )
589 {
590  static QPointF nullPoint( 0, 0 );
591 
592  QgsPaintEffect* effect = layer->paintEffect();
593  if ( effect && effect->enabled() )
594  {
595  QPainter* p = context.renderContext().painter();
596  p->save();
597  p->translate( point );
598 
599  effect->begin( context.renderContext() );
600  layer->renderPoint( nullPoint, context );
601  effect->end( context.renderContext() );
602 
603  p->restore();
604  }
605  else
606  {
607  layer->renderPoint( point, context );
608  }
609 }
610 
611 void QgsMarkerSymbolV2::renderPoint( const QPointF& point, const QgsFeature* f, QgsRenderContext& context, int layer, bool selected )
612 {
613  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, selected, mRenderHints, f, 0, mapUnitScale() );
614 
615  if ( layer != -1 )
616  {
617  if ( layer >= 0 && layer < mLayers.count() )
618  {
619  renderPointUsingLayer(( QgsMarkerSymbolLayerV2* ) mLayers[layer], point, symbolContext );
620  }
621  return;
622  }
623 
624  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
625  {
626  renderPointUsingLayer(( QgsMarkerSymbolLayerV2* ) * it, point, symbolContext );
627  }
628 }
629 
631 {
632  QgsSymbolV2* cloneSymbol = new QgsMarkerSymbolV2( cloneLayers() );
633  cloneSymbol->setAlpha( mAlpha );
634  cloneSymbol->setLayer( mLayer );
636  return cloneSymbol;
637 }
638 
639 
641 // LINE
642 
644  : QgsSymbolV2( Line, layers )
645 {
646  if ( mLayers.count() == 0 )
647  mLayers.append( new QgsSimpleLineSymbolLayerV2() );
648 }
649 
651 {
652  double origWidth = width();
653 
654  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
655  {
656  QgsLineSymbolLayerV2* layer = ( QgsLineSymbolLayerV2* ) * it;
657  if ( layer->width() == origWidth )
658  {
659  layer->setWidth( w );
660  }
661  else
662  {
663  // proportionally scale the width
664  if ( origWidth != 0 )
665  layer->setWidth( layer->width() * w / origWidth );
666  }
667  }
668 }
669 
671 {
672  double maxWidth = 0;
673  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
674  {
675  const QgsLineSymbolLayerV2* layer = ( const QgsLineSymbolLayerV2* ) * it;
676  double width = layer->width();
677  if ( width > maxWidth )
678  maxWidth = width;
679  }
680  return maxWidth;
681 }
682 
683 void QgsLineSymbolV2::renderPolyline( const QPolygonF& points, const QgsFeature* f, QgsRenderContext& context, int layer, bool selected )
684 {
685  //save old painter
686  QPainter* renderPainter = context.painter();
687  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, selected, mRenderHints, f, 0, mapUnitScale() );
688 
689  if ( layer != -1 )
690  {
691  if ( layer >= 0 && layer < mLayers.count() )
692  {
693  renderPolylineUsingLayer(( QgsLineSymbolLayerV2* ) mLayers[layer], points, symbolContext );
694  }
695  return;
696  }
697 
698  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
699  {
700  renderPolylineUsingLayer(( QgsLineSymbolLayerV2* ) * it, points, symbolContext );
701  }
702 
703  context.setPainter( renderPainter );
704 }
705 
706 void QgsLineSymbolV2::renderPolylineUsingLayer( QgsLineSymbolLayerV2 *layer, const QPolygonF &points, QgsSymbolV2RenderContext &context )
707 {
708  QgsPaintEffect* effect = layer->paintEffect();
709  if ( effect && effect->enabled() )
710  {
711  QPainter* p = context.renderContext().painter();
712  p->save();
713  p->translate( points.boundingRect().topLeft() );
714 
715  effect->begin( context.renderContext() );
716  layer->renderPolyline( points.translated( -points.boundingRect().topLeft() ), context );
717  effect->end( context.renderContext() );
718 
719  p->restore();
720  }
721  else
722  {
723  layer->renderPolyline( points, context );
724  }
725 }
726 
727 
729 {
730  QgsSymbolV2* cloneSymbol = new QgsLineSymbolV2( cloneLayers() );
731  cloneSymbol->setAlpha( mAlpha );
732  cloneSymbol->setLayer( mLayer );
734  return cloneSymbol;
735 }
736 
738 // FILL
739 
741  : QgsSymbolV2( Fill, layers )
742 {
743  if ( mLayers.count() == 0 )
744  mLayers.append( new QgsSimpleFillSymbolLayerV2() );
745 }
746 
747 void QgsFillSymbolV2::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, const QgsFeature* f, QgsRenderContext& context, int layer, bool selected )
748 {
749  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, selected, mRenderHints, f, 0, mapUnitScale() );
750 
751  if ( layer != -1 )
752  {
753  if ( layer >= 0 && layer < mLayers.count() )
754  {
755  renderPolygonUsingLayer( mLayers[layer], points, rings, symbolContext );
756  }
757  return;
758  }
759 
760  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
761  {
762  renderPolygonUsingLayer( *it, points, rings, symbolContext );
763  }
764 }
765 
766 void QgsFillSymbolV2::renderPolygonUsingLayer( QgsSymbolLayerV2* layer, const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context )
767 {
768  QgsSymbolV2::SymbolType layertype = layer->type();
769 
770  QgsPaintEffect* effect = layer->paintEffect();
771  if ( effect && effect->enabled() )
772  {
773  QRectF bounds = polygonBounds( points, rings );
774  QList<QPolygonF>* translatedRings = translateRings( rings, -bounds.left(), -bounds.top() );
775 
776  QPainter* p = context.renderContext().painter();
777  p->save();
778  p->translate( bounds.topLeft() );
779 
780  effect->begin( context.renderContext() );
781  if ( layertype == QgsSymbolV2::Fill )
782  {
783  (( QgsFillSymbolLayerV2* )layer )->renderPolygon( points.translated( -bounds.topLeft() ), translatedRings, context );
784  }
785  else if ( layertype == QgsSymbolV2::Line )
786  {
787  (( QgsLineSymbolLayerV2* )layer )->renderPolygonOutline( points.translated( -bounds.topLeft() ), translatedRings, context );
788  }
789  delete translatedRings;
790 
791  effect->end( context.renderContext() );
792  p->restore();
793  }
794  else
795  {
796  if ( layertype == QgsSymbolV2::Fill )
797  {
798  (( QgsFillSymbolLayerV2* )layer )->renderPolygon( points, rings, context );
799  }
800  else if ( layertype == QgsSymbolV2::Line )
801  {
802  (( QgsLineSymbolLayerV2* )layer )->renderPolygonOutline( points, rings, context );
803  }
804  }
805 }
806 
807 QRectF QgsFillSymbolV2::polygonBounds( const QPolygonF& points, const QList<QPolygonF>* rings ) const
808 {
809  QRectF bounds = points.boundingRect();
810  if ( rings )
811  {
812  QList<QPolygonF>::const_iterator it = rings->constBegin();
813  for ( ; it != rings->constEnd(); ++it )
814  {
815  bounds = bounds.united(( *it ).boundingRect() );
816  }
817  }
818  return bounds;
819 }
820 
821 QList<QPolygonF>* QgsFillSymbolV2::translateRings( const QList<QPolygonF>* rings, double dx, double dy ) const
822 {
823  if ( !rings )
824  return 0;
825 
826  QList<QPolygonF>* translatedRings = new QList<QPolygonF>;
827  QList<QPolygonF>::const_iterator it = rings->constBegin();
828  for ( ; it != rings->constEnd(); ++it )
829  {
830  translatedRings->append(( *it ).translated( dx, dy ) );
831  }
832  return translatedRings;
833 }
834 
836 {
837  QgsSymbolV2* cloneSymbol = new QgsFillSymbolV2( cloneLayers() );
838  cloneSymbol->setAlpha( mAlpha );
839  cloneSymbol->setLayer( mLayer );
841  return cloneSymbol;
842 }
843 
845 {
846  for ( QgsSymbolLayerV2List::iterator it = mLayers.begin(); it != mLayers.end(); ++it )
847  {
848  QgsFillSymbolLayerV2* layer = ( QgsFillSymbolLayerV2* ) * it;
849  layer->setAngle( angle );
850  }
851 }
852 
853 
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:172
QgsSymbolV2(SymbolType type, QgsSymbolLayerV2List layers)
Definition: qgssymbolv2.cpp:38
bool mClipFeaturesToExtent
Definition: qgssymbolv2.h:205
virtual double width() const
const QgsVectorLayer * mLayer
Definition: qgssymbolv2.h:207
SymbolType type() const
Definition: qgssymbolv2.h:85
QSet< QString > usedAttributes() const
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
static QString encodeSldUom(QgsSymbolV2::OutputUnit unit, double *scaleFactor)
void setScaleMethod(QgsSymbolV2::ScaleMethod scaleMethod)
QgsFillSymbolV2(QgsSymbolLayerV2List layers=QgsSymbolLayerV2List())
static QgsFillSymbolV2 * createSimple(const QgsStringMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties. ...
bool changeSymbolLayer(int index, QgsSymbolLayerV2 *layer)
delete layer at specified index and set a new one
ScaleMethod scaleMethod()
QgsMapUnitScale mapUnitScale() const
Definition: qgssymbolv2.cpp:90
Container of fields for a vector layer.
Definition: qgsfield.h:172
QgsSymbolV2 * symbol(QString name)
return a NEW copy of symbol
Definition: qgsstylev2.cpp:166
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:113
SymbolType mType
Definition: qgssymbolv2.h:198
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
QMap< QString, QString > QgsStringMap
Definition: qgis.h:438
static double pixelSizeScaleFactor(const QgsRenderContext &c, QgsSymbolV2::OutputUnit u, const QgsMapUnitScale &scale=QgsMapUnitScale())
Returns scale factor painter units -> pixel dimensions.
void setWidth(double width)
void setMapUnitScale(const QgsMapUnitScale &scale)
void setAngle(double angle)
const QgsVectorLayer * layer() const
Definition: qgssymbolv2.h:187
virtual void startRender(QgsSymbolV2RenderContext &context)=0
static QString encodeColor(QColor color)
void setColor(const QColor &color)
static QgsRenderContext createRenderContext(QPainter *p)
Creates a render context for a pixel based device.
QgsSymbolLayerV2List mLayers
Definition: qgssymbolv2.h:199
QgsSymbolLayerV2List cloneLayers() const
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 startRender(QgsRenderContext &context, const QgsFields *fields=0)
qreal alpha() const
Get alpha transparency 1 for opaque, 0 for invisible.
Definition: qgssymbolv2.h:157
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:186
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)
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:202
QgsSymbolV2RenderContext & operator=(const QgsSymbolV2RenderContext &)
virtual void renderPolygonOutline(const QPolygonF &points, QList< QPolygonF > *rings, QgsSymbolV2RenderContext &context)
void renderPoint(const QPointF &point, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
QgsSymbolV2::ScaleMethod scaleMethod() const
QgsSymbolV2::SymbolType type() 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()
Definition: qgssymbolv2.cpp:62
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)
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()
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:43
QgsRenderContext & renderContext()
Definition: qgssymbolv2.h:219
static QgsProject * instance()
access to canonical QgsProject instance
Definition: qgsproject.cpp:351
QgsSymbolV2::OutputUnit outputUnit() const
Definition: qgssymbolv2.cpp:69
QgsSymbolLayerV2 * takeSymbolLayer(int index)
remove symbol layer from the list and return pointer to it
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)
double size
Definition: qgssvgcache.cpp:77
virtual QgsSymbolV2 * clone() const override
virtual void stopRender(QgsSymbolV2RenderContext &context)=0
void setOutputUnit(QgsSymbolV2::OutputUnit u)
void setAlpha(qreal alpha)
Set alpha transparency 1 for opaque, 0 for invisible.
Definition: qgssymbolv2.h:159
QImage bigSymbolPreviewImage()
void setScaleMethod(QgsSymbolV2::ScaleMethod scaleMethod)
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the layer.
QColor color() const
int mRenderHints
Definition: qgssymbolv2.h:204