QGIS API Documentation  2.9.0-Master
qgsmarkersymbollayerv2.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmarkersymbollayerv2.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 "qgsmarkersymbollayerv2.h"
17 #include "qgssymbollayerv2utils.h"
18 
19 #include "qgsdxfexport.h"
20 #include "qgsdxfpaintdevice.h"
21 #include "qgsexpression.h"
22 #include "qgsrendercontext.h"
23 #include "qgslogger.h"
24 #include "qgssvgcache.h"
25 
26 #include <QPainter>
27 #include <QSvgRenderer>
28 #include <QFileInfo>
29 #include <QDir>
30 #include <QDomDocument>
31 #include <QDomElement>
32 
33 #include <cmath>
34 
35 Q_GUI_EXPORT extern int qt_defaultDpiX();
36 Q_GUI_EXPORT extern int qt_defaultDpiY();
37 
38 static void _fixQPictureDPI( QPainter* p )
39 {
40  // QPicture makes an assumption that we drawing to it with system DPI.
41  // Then when being drawn, it scales the painter. The following call
42  // negates the effect. There is no way of setting QPicture's DPI.
43  // See QTBUG-20361
44  p->scale(( double )qt_defaultDpiX() / p->device()->logicalDpiX(),
45  ( double )qt_defaultDpiY() / p->device()->logicalDpiY() );
46 }
47 
49 
50 QgsSimpleMarkerSymbolLayerV2::QgsSimpleMarkerSymbolLayerV2( QString name, QColor color, QColor borderColor, double size, double angle, QgsSymbolV2::ScaleMethod scaleMethod )
51  : mOutlineStyle( Qt::SolidLine ), mOutlineWidth( 0 ), mOutlineWidthUnit( QgsSymbolV2::MM )
52 {
53  mName = name;
54  mColor = color;
56  mSize = size;
57  mAngle = angle;
58  mOffset = QPointF( 0, 0 );
62  mUsingCache = false;
63 }
64 
66 {
73 
74  if ( props.contains( "name" ) )
75  name = props["name"];
76  if ( props.contains( "color" ) )
77  color = QgsSymbolLayerV2Utils::decodeColor( props["color"] );
78  if ( props.contains( "color_border" ) )
79  {
80  //pre 2.5 projects use "color_border"
81  borderColor = QgsSymbolLayerV2Utils::decodeColor( props["color_border"] );
82  }
83  else if ( props.contains( "outline_color" ) )
84  {
85  borderColor = QgsSymbolLayerV2Utils::decodeColor( props["outline_color"] );
86  }
87  else if ( props.contains( "line_color" ) )
88  {
89  borderColor = QgsSymbolLayerV2Utils::decodeColor( props["line_color"] );
90  }
91  if ( props.contains( "size" ) )
92  size = props["size"].toDouble();
93  if ( props.contains( "angle" ) )
94  angle = props["angle"].toDouble();
95  if ( props.contains( "scale_method" ) )
96  scaleMethod = QgsSymbolLayerV2Utils::decodeScaleMethod( props["scale_method"] );
97 
98  QgsSimpleMarkerSymbolLayerV2* m = new QgsSimpleMarkerSymbolLayerV2( name, color, borderColor, size, angle, scaleMethod );
99  if ( props.contains( "offset" ) )
100  m->setOffset( QgsSymbolLayerV2Utils::decodePoint( props["offset"] ) );
101  if ( props.contains( "offset_unit" ) )
102  m->setOffsetUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["offset_unit"] ) );
103  if ( props.contains( "offset_map_unit_scale" ) )
104  m->setOffsetMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( props["offset_map_unit_scale"] ) );
105  if ( props.contains( "size_unit" ) )
106  m->setSizeUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["size_unit"] ) );
107  if ( props.contains( "size_map_unit_scale" ) )
108  m->setSizeMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( props["size_map_unit_scale"] ) );
109 
110  if ( props.contains( "outline_style" ) )
111  {
112  m->setOutlineStyle( QgsSymbolLayerV2Utils::decodePenStyle( props["outline_style"] ) );
113  }
114  else if ( props.contains( "line_style" ) )
115  {
116  m->setOutlineStyle( QgsSymbolLayerV2Utils::decodePenStyle( props["line_style"] ) );
117  }
118  if ( props.contains( "outline_width" ) )
119  {
120  m->setOutlineWidth( props["outline_width"].toDouble() );
121  }
122  else if ( props.contains( "line_width" ) )
123  {
124  m->setOutlineWidth( props["line_width"].toDouble() );
125  }
126  if ( props.contains( "outline_width_unit" ) )
127  {
128  m->setOutlineWidthUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["outline_width_unit"] ) );
129  }
130  if ( props.contains( "line_width_unit" ) )
131  {
132  m->setOutlineWidthUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["line_width_unit"] ) );
133  }
134  if ( props.contains( "outline_width_map_unit_scale" ) )
135  {
136  m->setOutlineWidthMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( props["outline_width_map_unit_scale"] ) );
137  }
138 
139  if ( props.contains( "horizontal_anchor_point" ) )
140  {
141  m->setHorizontalAnchorPoint( QgsMarkerSymbolLayerV2::HorizontalAnchorPoint( props[ "horizontal_anchor_point" ].toInt() ) );
142  }
143  if ( props.contains( "vertical_anchor_point" ) )
144  {
145  m->setVerticalAnchorPoint( QgsMarkerSymbolLayerV2::VerticalAnchorPoint( props[ "vertical_anchor_point" ].toInt() ) );
146  }
147 
148  m->restoreDataDefinedProperties( props );
149 
150  return m;
151 }
152 
153 
155 {
156  return "SimpleMarker";
157 }
158 
160 {
161  QColor brushColor = mColor;
162  QColor penColor = mBorderColor;
163 
164  brushColor.setAlphaF( mColor.alphaF() * context.alpha() );
165  penColor.setAlphaF( mBorderColor.alphaF() * context.alpha() );
166 
167  mBrush = QBrush( brushColor );
168  mPen = QPen( penColor );
169  mPen.setStyle( mOutlineStyle );
171 
172  QColor selBrushColor = context.renderContext().selectionColor();
173  QColor selPenColor = selBrushColor == mColor ? selBrushColor : mBorderColor;
174  if ( context.alpha() < 1 )
175  {
176  selBrushColor.setAlphaF( context.alpha() );
177  selPenColor.setAlphaF( context.alpha() );
178  }
179  mSelBrush = QBrush( selBrushColor );
180  mSelPen = QPen( selPenColor );
181  mSelPen.setStyle( mOutlineStyle );
183 
186 
187  // use caching only when:
188  // - size, rotation, shape, color, border color is not data-defined
189  // - drawing to screen (not printer)
190  mUsingCache = !hasDataDefinedRotation && !hasDataDefinedSize && !context.renderContext().forceVectorOutput()
194 
195  // use either QPolygonF or QPainterPath for drawing
196  // TODO: find out whether drawing directly doesn't bring overhead - if not, use it for all shapes
197  if ( !prepareShape() ) // drawing as a polygon
198  {
199  if ( preparePath() ) // drawing as a painter path
200  {
201  // some markers can't be drawn as a polygon (circle, cross)
202  // For these set the selected border color to the selected color
203 
204  if ( mName != "circle" )
205  mSelPen.setColor( selBrushColor );
206  }
207  else
208  {
209  QgsDebugMsg( "unknown symbol" );
210  return;
211  }
212  }
213 
214  QMatrix transform;
215 
216  // scale the shape (if the size is not going to be modified)
217  if ( !hasDataDefinedSize )
218  {
220  if ( mUsingCache )
221  scaledSize *= context.renderContext().rasterScaleFactor();
222  double half = scaledSize / 2.0;
223  transform.scale( half, half );
224  }
225 
226  // rotate if the rotation is not going to be changed during the rendering
227  if ( !hasDataDefinedRotation && mAngle != 0 )
228  {
229  transform.rotate( mAngle );
230  }
231 
232  if ( !mPolygon.isEmpty() )
233  mPolygon = transform.map( mPolygon );
234  else
235  mPath = transform.map( mPath );
236 
237  if ( mUsingCache )
238  {
239  if ( !prepareCache( context ) )
240  {
241  mUsingCache = false;
242  }
243  }
244  else
245  {
246  mCache = QImage();
247  mSelCache = QImage();
248  }
249 
250  prepareExpressions( context.fields(), context.renderContext().rendererScale() );
251 
253 }
254 
255 
257 {
259 
260  // calculate necessary image size for the cache
261  double pw = (( mPen.widthF() == 0 ? 1 : mPen.widthF() ) + 1 ) / 2 * 2; // make even (round up); handle cosmetic pen
262  int imageSize = (( int ) scaledSize + pw ) / 2 * 2 + 1; // make image width, height odd; account for pen width
263  double center = imageSize / 2.0;
264 
265  if ( imageSize > mMaximumCacheWidth )
266  {
267  return false;
268  }
269 
270  mCache = QImage( QSize( imageSize, imageSize ), QImage::Format_ARGB32_Premultiplied );
271  mCache.fill( 0 );
272 
273  QPainter p;
274  p.begin( &mCache );
275  p.setRenderHint( QPainter::Antialiasing );
276  p.setBrush( mBrush );
277  p.setPen( mPen );
278  p.translate( QPointF( center, center ) );
279  drawMarker( &p, context );
280  p.end();
281 
282  // Construct the selected version of the Cache
283 
284  QColor selColor = context.renderContext().selectionColor();
285 
286  mSelCache = QImage( QSize( imageSize, imageSize ), QImage::Format_ARGB32_Premultiplied );
287  mSelCache.fill( 0 );
288 
289  p.begin( &mSelCache );
290  p.setRenderHint( QPainter::Antialiasing );
291  p.setBrush( mSelBrush );
292  p.setPen( mSelPen );
293  p.translate( QPointF( center, center ) );
294  drawMarker( &p, context );
295  p.end();
296 
297  // Check that the selected version is different. If not, then re-render,
298  // filling the background with the selection color and using the normal
299  // colors for the symbol .. could be ugly!
300 
301  if ( mSelCache == mCache )
302  {
303  p.begin( &mSelCache );
304  p.setRenderHint( QPainter::Antialiasing );
305  p.fillRect( 0, 0, imageSize, imageSize, selColor );
306  p.setBrush( mBrush );
307  p.setPen( mPen );
308  p.translate( QPointF( center, center ) );
309  drawMarker( &p, context );
310  p.end();
311  }
312 
313  return true;
314 }
315 
317 {
318  Q_UNUSED( context );
319 }
320 
322 {
323  mPolygon.clear();
324 
325  if ( name.isNull() )
326  {
327  name = mName;
328  }
329 
330  if ( name == "square" || name == "rectangle" )
331  {
332  mPolygon = QPolygonF( QRectF( QPointF( -1, -1 ), QPointF( 1, 1 ) ) );
333  return true;
334  }
335  else if ( name == "diamond" )
336  {
337  mPolygon << QPointF( -1, 0 ) << QPointF( 0, 1 )
338  << QPointF( 1, 0 ) << QPointF( 0, -1 );
339  return true;
340  }
341  else if ( name == "pentagon" )
342  {
343  mPolygon << QPointF( sin( DEG2RAD( 288.0 ) ), - cos( DEG2RAD( 288.0 ) ) )
344  << QPointF( sin( DEG2RAD( 216.0 ) ), - cos( DEG2RAD( 216.0 ) ) )
345  << QPointF( sin( DEG2RAD( 144.0 ) ), - cos( DEG2RAD( 144.0 ) ) )
346  << QPointF( sin( DEG2RAD( 72.0 ) ), - cos( DEG2RAD( 72.0 ) ) )
347  << QPointF( 0, -1 );
348  return true;
349  }
350  else if ( name == "triangle" )
351  {
352  mPolygon << QPointF( -1, 1 ) << QPointF( 1, 1 ) << QPointF( 0, -1 );
353  return true;
354  }
355  else if ( name == "equilateral_triangle" )
356  {
357  mPolygon << QPointF( sin( DEG2RAD( 240.0 ) ), - cos( DEG2RAD( 240.0 ) ) )
358  << QPointF( sin( DEG2RAD( 120.0 ) ), - cos( DEG2RAD( 120.0 ) ) )
359  << QPointF( 0, -1 );
360  return true;
361  }
362  else if ( name == "star" )
363  {
364  double sixth = 1.0 / 3;
365 
366  mPolygon << QPointF( 0, -1 )
367  << QPointF( -sixth, -sixth )
368  << QPointF( -1, -sixth )
369  << QPointF( -sixth, 0 )
370  << QPointF( -1, 1 )
371  << QPointF( 0, + sixth )
372  << QPointF( 1, 1 )
373  << QPointF( + sixth, 0 )
374  << QPointF( 1, -sixth )
375  << QPointF( + sixth, -sixth );
376  return true;
377  }
378  else if ( name == "regular_star" )
379  {
380  double inner_r = cos( DEG2RAD( 72.0 ) ) / cos( DEG2RAD( 36.0 ) );
381 
382  mPolygon << QPointF( inner_r * sin( DEG2RAD( 324.0 ) ), - inner_r * cos( DEG2RAD( 324.0 ) ) ) // 324
383  << QPointF( sin( DEG2RAD( 288.0 ) ), - cos( DEG2RAD( 288 ) ) ) // 288
384  << QPointF( inner_r * sin( DEG2RAD( 252.0 ) ), - inner_r * cos( DEG2RAD( 252.0 ) ) ) // 252
385  << QPointF( sin( DEG2RAD( 216.0 ) ), - cos( DEG2RAD( 216.0 ) ) ) // 216
386  << QPointF( 0, inner_r ) // 180
387  << QPointF( sin( DEG2RAD( 144.0 ) ), - cos( DEG2RAD( 144.0 ) ) ) // 144
388  << QPointF( inner_r * sin( DEG2RAD( 108.0 ) ), - inner_r * cos( DEG2RAD( 108.0 ) ) ) // 108
389  << QPointF( sin( DEG2RAD( 72.0 ) ), - cos( DEG2RAD( 72.0 ) ) ) // 72
390  << QPointF( inner_r * sin( DEG2RAD( 36.0 ) ), - inner_r * cos( DEG2RAD( 36.0 ) ) ) // 36
391  << QPointF( 0, -1 ); // 0
392  return true;
393  }
394  else if ( name == "arrow" )
395  {
396  mPolygon
397  << QPointF( 0, -1 )
398  << QPointF( 0.5, -0.5 )
399  << QPointF( 0.25, -0.5 )
400  << QPointF( 0.25, 1 )
401  << QPointF( -0.25, 1 )
402  << QPointF( -0.25, -0.5 )
403  << QPointF( -0.5, -0.5 );
404  return true;
405  }
406  else if ( name == "filled_arrowhead" )
407  {
408  mPolygon << QPointF( 0, 0 ) << QPointF( -1, 1 ) << QPointF( -1, -1 );
409  return true;
410  }
411 
412  return false;
413 }
414 
416 {
417  mPath = QPainterPath();
418  if ( name.isNull() )
419  {
420  name = mName;
421  }
422 
423  if ( name == "circle" )
424  {
425  mPath.addEllipse( QRectF( -1, -1, 2, 2 ) ); // x,y,w,h
426  return true;
427  }
428  else if ( name == "cross" )
429  {
430  mPath.moveTo( -1, 0 );
431  mPath.lineTo( 1, 0 ); // horizontal
432  mPath.moveTo( 0, -1 );
433  mPath.lineTo( 0, 1 ); // vertical
434  return true;
435  }
436  else if ( name == "x" || name == "cross2" )
437  {
438  mPath.moveTo( -1, -1 );
439  mPath.lineTo( 1, 1 );
440  mPath.moveTo( 1, -1 );
441  mPath.lineTo( -1, 1 );
442  return true;
443  }
444  else if ( name == "line" )
445  {
446  mPath.moveTo( 0, -1 );
447  mPath.lineTo( 0, 1 ); // vertical line
448  return true;
449  }
450  else if ( name == "arrowhead" )
451  {
452  mPath.moveTo( 0, 0 );
453  mPath.lineTo( -1, -1 );
454  mPath.moveTo( 0, 0 );
455  mPath.lineTo( -1, 1 );
456  return true;
457  }
458 
459  return false;
460 }
461 
463 {
464  QPainter *p = context.renderContext().painter();
465  if ( !p )
466  {
467  return;
468  }
469 
470  double scaledSize = mSize;
471 
473 
474  bool ok = true;
476  {
477  scaledSize = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_SIZE, context.feature(), mSize, &ok ).toDouble();
478  }
479 
480  if ( hasDataDefinedSize && ok )
481  {
482  switch ( mScaleMethod )
483  {
485  scaledSize = sqrt( scaledSize );
486  break;
488  break;
489  }
490  }
491 
492  //offset
493  double offsetX = 0;
494  double offsetY = 0;
495  markerOffset( context, scaledSize, scaledSize, offsetX, offsetY );
496  QPointF off( offsetX, offsetY );
497 
498  //angle
499  double angle = mAngle + mLineAngle;
500  bool usingDataDefinedRotation = false;
502  {
503  angle = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_ANGLE, context.feature(), mAngle, &ok ).toDouble() + mLineAngle;
504  usingDataDefinedRotation = ok;
505  }
506 
507  bool hasDataDefinedRotation = context.renderHints() & QgsSymbolV2::DataDefinedRotation || usingDataDefinedRotation;
508  if ( hasDataDefinedRotation )
509  {
510  // For non-point markers, "dataDefinedRotation" means following the
511  // shape (shape-data defined). For them, "field-data defined" does
512  // not work at all. TODO: if "field-data defined" ever gets implemented
513  // we'll need a way to distinguish here between the two, possibly
514  // using another flag in renderHints()
515  const QgsFeature* f = context.feature();
516  if ( f )
517  {
518  const QgsGeometry *g = f->constGeometry();
519  if ( g && g->type() == QGis::Point )
520  {
521  const QgsMapToPixel& m2p = context.renderContext().mapToPixel();
522  angle += m2p.mapRotation();
523  }
524  }
525  }
526 
527  if ( angle )
528  off = _rotatedOffset( off, angle );
529 
530  //data defined shape?
531  bool createdNewPath = false;
533  {
534  QString name = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_NAME, context.feature(), QVariant(), &ok ).toString();
535  if ( ok )
536  {
537  if ( !prepareShape( name ) ) // drawing as a polygon
538  {
539  preparePath( name ); // drawing as a painter path
540  }
541  createdNewPath = true;
542  }
543  }
544 
545  if ( mUsingCache )
546  {
547  //QgsDebugMsg( QString("XXX using cache") );
548  // we will use cached image
549  QImage &img = context.selected() ? mSelCache : mCache;
550  double s = img.width() / context.renderContext().rasterScaleFactor();
551  p->drawImage( QRectF( point.x() - s / 2.0 + off.x(),
552  point.y() - s / 2.0 + off.y(),
553  s, s ), img );
554  }
555  else
556  {
557  QMatrix transform;
558 
559  // move to the desired position
560  transform.translate( point.x() + off.x(), point.y() + off.y() );
561 
562  // resize if necessary
563  if ( hasDataDefinedSize || createdNewPath )
564  {
566  double half = s / 2.0;
567  transform.scale( half, half );
568  }
569 
570  if ( angle != 0 && ( hasDataDefinedRotation || createdNewPath ) )
571  transform.rotate( angle );
572 
574  {
575  QString colorString = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_COLOR, context.feature(), QVariant(), &ok ).toString();
576  if ( ok )
577  mBrush.setColor( QgsSymbolLayerV2Utils::decodeColor( colorString ) );
578  }
580  {
581  QString colorString = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_COLOR_BORDER, context.feature(), QVariant(), &ok ).toString();
582  if ( ok )
583  {
584  mPen.setColor( QgsSymbolLayerV2Utils::decodeColor( colorString ) );
585  mSelPen.setColor( QgsSymbolLayerV2Utils::decodeColor( colorString ) );
586  }
587  }
589  {
590  double outlineWidth = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH, context.feature(), QVariant(), &ok ).toDouble();
591  if ( ok )
592  {
595  }
596  }
598  {
599  QString outlineStyle = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_STYLE, context.feature(), QVariant(), &ok ).toString();
600  if ( ok )
601  {
602  mPen.setStyle( QgsSymbolLayerV2Utils::decodePenStyle( outlineStyle ) );
603  mSelPen.setStyle( QgsSymbolLayerV2Utils::decodePenStyle( outlineStyle ) );
604  }
605  }
606 
607  p->setBrush( context.selected() ? mSelBrush : mBrush );
608  p->setPen( context.selected() ? mSelPen : mPen );
609 
610  if ( !mPolygon.isEmpty() )
611  p->drawPolygon( transform.map( mPolygon ) );
612  else
613  p->drawPath( transform.map( mPath ) );
614  }
615 }
616 
617 
619 {
620  QgsStringMap map;
621  map["name"] = mName;
622  map["color"] = QgsSymbolLayerV2Utils::encodeColor( mColor );
623  map["outline_color"] = QgsSymbolLayerV2Utils::encodeColor( mBorderColor );
624  map["size"] = QString::number( mSize );
626  map["size_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mSizeMapUnitScale );
627  map["angle"] = QString::number( mAngle );
628  map["offset"] = QgsSymbolLayerV2Utils::encodePoint( mOffset );
630  map["offset_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOffsetMapUnitScale );
632  map["outline_style"] = QgsSymbolLayerV2Utils::encodePenStyle( mOutlineStyle );
633  map["outline_width"] = QString::number( mOutlineWidth );
634  map["outline_width_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mOutlineWidthUnit );
635  map["outline_width_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOutlineWidthMapUnitScale );
636  map["horizontal_anchor_point"] = QString::number( mHorizontalAnchorPoint );
637  map["vertical_anchor_point"] = QString::number( mVerticalAnchorPoint );
638 
639 
640  //data define properties
642  return map;
643 }
644 
646 {
648  m->setOffset( mOffset );
649  m->setSizeUnit( mSizeUnit );
660  copyPaintEffect( m );
661  return m;
662 }
663 
664 void QgsSimpleMarkerSymbolLayerV2::writeSldMarker( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const
665 {
666  // <Graphic>
667  QDomElement graphicElem = doc.createElement( "se:Graphic" );
668  element.appendChild( graphicElem );
669 
671 
672  // <Rotation>
673  QString angleFunc;
674  bool ok;
675  double angle = props.value( "angle", "0" ).toDouble( &ok );
676  if ( !ok )
677  {
678  angleFunc = QString( "%1 + %2" ).arg( props.value( "angle", "0" ) ).arg( mAngle );
679  }
680  else if ( angle + mAngle != 0 )
681  {
682  angleFunc = QString::number( angle + mAngle );
683  }
684  QgsSymbolLayerV2Utils::createRotationElement( doc, graphicElem, angleFunc );
685 
686  // <Displacement>
688 }
689 
690 QString QgsSimpleMarkerSymbolLayerV2::ogrFeatureStyle( double mmScaleFactor, double mapUnitScaleFactor ) const
691 {
692  Q_UNUSED( mmScaleFactor );
693  Q_UNUSED( mapUnitScaleFactor );
694 #if 0
695  QString ogrType = "3"; //default is circle
696  if ( mName == "square" )
697  {
698  ogrType = "5";
699  }
700  else if ( mName == "triangle" )
701  {
702  ogrType = "7";
703  }
704  else if ( mName == "star" )
705  {
706  ogrType = "9";
707  }
708  else if ( mName == "circle" )
709  {
710  ogrType = "3";
711  }
712  else if ( mName == "cross" )
713  {
714  ogrType = "0";
715  }
716  else if ( mName == "x" || mName == "cross2" )
717  {
718  ogrType = "1";
719  }
720  else if ( mName == "line" )
721  {
722  ogrType = "10";
723  }
724 
725  QString ogrString;
726  ogrString.append( "SYMBOL(" );
727  ogrString.append( "id:" );
728  ogrString.append( "\"" );
729  ogrString.append( "ogr-sym-" );
730  ogrString.append( ogrType );
731  ogrString.append( "\"" );
732  ogrString.append( ",c:" );
733  ogrString.append( mColor.name() );
734  ogrString.append( ",o:" );
735  ogrString.append( mBorderColor.name() );
736  ogrString.append( QString( ",s:%1mm" ).arg( mSize ) );
737  ogrString.append( ")" );
738  return ogrString;
739 #endif //0
740 
741  QString ogrString;
742  ogrString.append( "PEN(" );
743  ogrString.append( "c:" );
744  ogrString.append( mColor.name() );
745  ogrString.append( ",w:" );
746  ogrString.append( QString::number( mSize ) );
747  ogrString.append( "mm" );
748  ogrString.append( ")" );
749  return ogrString;
750 }
751 
753 {
754  QgsDebugMsg( "Entered." );
755 
756  QDomElement graphicElem = element.firstChildElement( "Graphic" );
757  if ( graphicElem.isNull() )
758  return NULL;
759 
760  QString name = "square";
761  QColor color, borderColor;
762  double borderWidth, size;
763  Qt::PenStyle borderStyle;
764 
765  if ( !QgsSymbolLayerV2Utils::wellKnownMarkerFromSld( graphicElem, name, color, borderColor, borderStyle, borderWidth, size ) )
766  return NULL;
767 
768  double angle = 0.0;
769  QString angleFunc;
770  if ( QgsSymbolLayerV2Utils::rotationFromSldElement( graphicElem, angleFunc ) )
771  {
772  bool ok;
773  double d = angleFunc.toDouble( &ok );
774  if ( ok )
775  angle = d;
776  }
777 
778  QPointF offset;
780 
781  QgsSimpleMarkerSymbolLayerV2 *m = new QgsSimpleMarkerSymbolLayerV2( name, color, borderColor, size );
782  m->setAngle( angle );
783  m->setOffset( offset );
784  m->setOutlineStyle( borderStyle );
785  return m;
786 }
787 
789 {
790  Q_UNUSED( context );
791 
792  if ( mPolygon.count() != 0 )
793  {
794  p->drawPolygon( mPolygon );
795  }
796  else
797  {
798  p->drawPath( mPath );
799  }
800 }
801 
802 bool QgsSimpleMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, const QPointF& shift ) const
803 {
804  //data defined size?
805  double size = mSize;
806 
807  bool hasDataDefinedSize = false;
808  if ( context )
809  {
811  }
812 
813  //data defined size
814  bool ok = true;
815  if ( hasDataDefinedSize )
816  {
818  {
819  size = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_SIZE, f, mSize, &ok ).toDouble();
820  }
821 
822  if ( ok )
823  {
824  switch ( mScaleMethod )
825  {
827  size = sqrt( size );
828  break;
830  break;
831  }
832  }
833 
835  }
836  if ( mSizeUnit == QgsSymbolV2::MM )
837  {
838  size *= mmMapUnitScaleFactor;
839  }
840  double halfSize = size / 2.0;
841 
842  //outlineWidth
843  double outlineWidth = mOutlineWidth;
844 
846  {
848  }
849  if ( mSizeUnit == QgsSymbolV2::MM )
850  {
851  outlineWidth *= mmMapUnitScaleFactor;
852  }
853 
854  //color
855  QColor pc = mPen.color();
856  QColor bc = mBrush.color();
858  {
859  QString colorString = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_COLOR, f, QVariant(), &ok ).toString();
860  if ( ok )
861  bc = QgsSymbolLayerV2Utils::decodeColor( colorString );
862  }
864  {
865  QString colorString = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_COLOR_BORDER, f, QVariant(), &ok ).toString();
866  if ( ok )
867  pc = QgsSymbolLayerV2Utils::decodeColor( colorString );
868  }
869 
870  //offset
871  double offsetX = 0;
872  double offsetY = 0;
873  if ( context )
874  {
875  markerOffset( *context, offsetX, offsetY );
876  }
877  QPointF off( offsetX, offsetY );
878 
879  //angle
880  double angle = mAngle + mLineAngle;
882  {
884  }
885 
886  angle = -angle; //rotation in Qt is counterclockwise
887  if ( angle )
888  off = _rotatedOffset( off, angle );
889 
890  if ( mSizeUnit == QgsSymbolV2::MM )
891  {
892  off *= mmMapUnitScaleFactor;
893  }
894 
895  QTransform t;
896  t.translate( shift.x() + offsetX, shift.y() + offsetY );
897 
898  if ( angle != 0 )
899  t.rotate( angle );
900 
901  //data defined symbol name
902 
903  if ( mName == "circle" )
904  {
905  if ( mBrush.style() != Qt::NoBrush )
906  e.writeFilledCircle( layerName, bc, shift, halfSize );
907  if ( mPen.style() != Qt::NoPen )
908  e.writeCircle( layerName, pc, shift, halfSize, "CONTINUOUS", outlineWidth );
909  }
910  else if ( mName == "square" || mName == "rectangle" )
911  {
912  // pt1 pt2
913  // pt3 pt4
914  QPointF pt1 = t.map( QPointF( -halfSize, -halfSize ) );
915  QPointF pt2 = t.map( QPointF( halfSize, -halfSize ) );
916  QPointF pt3 = t.map( QPointF( -halfSize, halfSize ) );
917  QPointF pt4 = t.map( QPointF( halfSize, halfSize ) );
918 
919  if ( mBrush.style() != Qt::NoBrush )
920  e.writeSolid( layerName, bc, pt1, pt2, pt3, pt4 );
921 
922  if ( mPen.style() != Qt::NoPen )
923  {
924  e.writeLine( pt1, pt2, layerName, "CONTINUOUS", pc, outlineWidth );
925  e.writeLine( pt2, pt4, layerName, "CONTINUOUS", pc, outlineWidth );
926  e.writeLine( pt4, pt3, layerName, "CONTINUOUS", pc, outlineWidth );
927  e.writeLine( pt3, pt1, layerName, "CONTINUOUS", pc, outlineWidth );
928  }
929  }
930  else if ( mName == "diamond" )
931  {
932  QPointF pt1 = t.map( QPointF( -halfSize, 0 ) );
933  QPointF pt2 = t.map( QPointF( 0, -halfSize ) );
934  QPointF pt3 = t.map( QPointF( 0, halfSize ) );
935  QPointF pt4 = t.map( QPointF( halfSize, 0 ) );
936 
937  if ( mBrush.style() != Qt::NoBrush )
938  e.writeSolid( layerName, bc, pt1, pt2, pt3, pt4 );
939 
940  if ( mPen.style() != Qt::NoPen )
941  {
942  e.writeLine( pt1, pt2, layerName, "CONTINUOUS", pc, outlineWidth );
943  e.writeLine( pt2, pt3, layerName, "CONTINUOUS", pc, outlineWidth );
944  e.writeLine( pt3, pt4, layerName, "CONTINUOUS", pc, outlineWidth );
945  e.writeLine( pt4, pt1, layerName, "CONTINUOUS", pc, outlineWidth );
946  }
947  }
948  else if ( mName == "triangle" )
949  {
950  QPointF pt1 = t.map( QPointF( -halfSize, -halfSize ) );
951  QPointF pt2 = t.map( QPointF( halfSize, -halfSize ) );
952  QPointF pt3 = t.map( QPointF( 0, halfSize ) );
953 
954  if ( mBrush.style() != Qt::NoBrush )
955  e.writeSolid( layerName, bc, pt1, pt2, pt3, pt3 );
956 
957  if ( mPen.style() != Qt::NoPen )
958  {
959  e.writeLine( pt1, pt2, layerName, "CONTINUOUS", pc, outlineWidth );
960  e.writeLine( pt2, pt3, layerName, "CONTINUOUS", pc, outlineWidth );
961  e.writeLine( pt3, pt1, layerName, "CONTINUOUS", pc, outlineWidth );
962  }
963  }
964 #if 0
965  else if ( mName == "equilateral_triangle" )
966  {
967 
968  }
969 #endif
970  else if ( mName == "line" )
971  {
972  QPointF pt1 = t.map( QPointF( 0, halfSize ) );
973  QPointF pt2 = t.map( QPointF( 0, -halfSize ) );
974 
975  if ( mPen.style() != Qt::NoPen )
976  e.writeLine( pt1, pt2, layerName, "CONTINUOUS", pc, outlineWidth );
977  }
978  else if ( mName == "cross" )
979  {
980  QPointF pt1 = t.map( QPointF( -halfSize, 0 ) );
981  QPointF pt2 = t.map( QPointF( halfSize, 0 ) );
982  QPointF pt3 = t.map( QPointF( 0, -halfSize ) );
983  QPointF pt4 = t.map( QPointF( 0, halfSize ) );
984 
985  if ( mPen.style() != Qt::NoPen )
986  {
987  e.writeLine( pt1, pt2, layerName, "CONTINUOUS", pc, outlineWidth );
988  e.writeLine( pt3, pt4, layerName, "CONTINUOUS", pc, outlineWidth );
989  }
990  }
991  else if ( mName == "x" || mName == "cross2" )
992  {
993  QPointF pt1 = t.map( QPointF( -halfSize, -halfSize ) );
994  QPointF pt2 = t.map( QPointF( halfSize, halfSize ) );
995  QPointF pt3 = t.map( QPointF( -halfSize, halfSize ) );
996  QPointF pt4 = t.map( QPointF( halfSize, -halfSize ) );
997 
998  if ( mPen.style() != Qt::NoPen )
999  {
1000  e.writeLine( pt1, pt2, layerName, "CONTINUOUS", pc, outlineWidth );
1001  e.writeLine( pt3, pt4, layerName, "CONTINUOUS", pc, outlineWidth );
1002  }
1003  }
1004  else if ( mName == "arrowhead" )
1005  {
1006  QPointF pt1 = t.map( QPointF( -halfSize, halfSize ) );
1007  QPointF pt2 = t.map( QPointF( 0, 0 ) );
1008  QPointF pt3 = t.map( QPointF( -halfSize, -halfSize ) );
1009 
1010  if ( mPen.style() != Qt::NoPen )
1011  {
1012  e.writeLine( pt1, pt2, layerName, "CONTINUOUS", pc, outlineWidth );
1013  e.writeLine( pt3, pt2, layerName, "CONTINUOUS", pc, outlineWidth );
1014  }
1015  }
1016  else if ( mName == "filled_arrowhead" )
1017  {
1018  QPointF pt1 = t.map( QPointF( -halfSize, halfSize ) );
1019  QPointF pt2 = t.map( QPointF( 0, 0 ) );
1020  QPointF pt3 = t.map( QPointF( -halfSize, -halfSize ) );
1021 
1022  if ( mBrush.style() != Qt::NoBrush )
1023  {
1024  e.writeSolid( layerName, bc, pt1, pt2, pt3, pt3 );
1025  }
1026  }
1027  else
1028  {
1029  return false;
1030  }
1031 
1032  return true;
1033 }
1034 
1035 
1037 {
1039  mOutlineWidthUnit = unit;
1040 }
1041 
1043 {
1045  {
1046  return mOutlineWidthUnit;
1047  }
1048  return QgsSymbolV2::Mixed;
1049 }
1050 
1052 {
1054  mOutlineWidthMapUnitScale = scale;
1055 }
1056 
1058 {
1060  {
1062  }
1063  return QgsMapUnitScale();
1064 }
1065 
1067 
1068 
1070 {
1072  mSize = size;
1073  mAngle = angle;
1074  mOffset = QPointF( 0, 0 );
1076  mOutlineWidth = 1.0;
1078  mFillColor = QColor( Qt::black );
1079  mOutlineColor = QColor( Qt::black );
1080 }
1081 
1082 
1084 {
1085  QString name = DEFAULT_SVGMARKER_NAME;
1086  double size = DEFAULT_SVGMARKER_SIZE;
1087  double angle = DEFAULT_SVGMARKER_ANGLE;
1089 
1090  if ( props.contains( "name" ) )
1091  name = props["name"];
1092  if ( props.contains( "size" ) )
1093  size = props["size"].toDouble();
1094  if ( props.contains( "angle" ) )
1095  angle = props["angle"].toDouble();
1096  if ( props.contains( "scale_method" ) )
1097  scaleMethod = QgsSymbolLayerV2Utils::decodeScaleMethod( props["scale_method"] );
1098 
1099  QgsSvgMarkerSymbolLayerV2* m = new QgsSvgMarkerSymbolLayerV2( name, size, angle, scaleMethod );
1100 
1101  //we only check the svg default parameters if necessary, since it could be expensive
1102  if ( !props.contains( "fill" ) && !props.contains( "color" ) && !props.contains( "outline" ) &&
1103  !props.contains( "outline_color" ) && !props.contains( "outline-width" ) && !props.contains( "outline_width" ) )
1104  {
1105  QColor fillColor, outlineColor;
1106  double outlineWidth;
1107  bool hasFillParam, hasOutlineParam, hasOutlineWidthParam;
1108  QgsSvgCache::instance()->containsParams( name, hasFillParam, fillColor, hasOutlineParam, outlineColor, hasOutlineWidthParam, outlineWidth );
1109  if ( hasFillParam )
1110  {
1111  m->setFillColor( fillColor );
1112  }
1113  if ( hasOutlineParam )
1114  {
1115  m->setOutlineColor( outlineColor );
1116  }
1117  if ( hasOutlineWidthParam )
1118  {
1119  m->setOutlineWidth( outlineWidth );
1120  }
1121  }
1122 
1123  if ( props.contains( "size_unit" ) )
1124  m->setSizeUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["size_unit"] ) );
1125  if ( props.contains( "size_map_unit_scale" ) )
1126  m->setSizeMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( props["size_map_unit_scale"] ) );
1127  if ( props.contains( "offset" ) )
1128  m->setOffset( QgsSymbolLayerV2Utils::decodePoint( props["offset"] ) );
1129  if ( props.contains( "offset_unit" ) )
1130  m->setOffsetUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["offset_unit"] ) );
1131  if ( props.contains( "offset_map_unit_scale" ) )
1132  m->setOffsetMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( props["offset_map_unit_scale"] ) );
1133  if ( props.contains( "fill" ) )
1134  {
1135  //pre 2.5 projects used "fill"
1136  m->setFillColor( QColor( props["fill"] ) );
1137  }
1138  else if ( props.contains( "color" ) )
1139  {
1140  m->setFillColor( QColor( props["color"] ) );
1141  }
1142  if ( props.contains( "outline" ) )
1143  {
1144  //pre 2.5 projects used "outline"
1145  m->setOutlineColor( QColor( props["outline"] ) );
1146  }
1147  else if ( props.contains( "outline_color" ) )
1148  {
1149  m->setOutlineColor( QColor( props["outline_color"] ) );
1150  }
1151  else if ( props.contains( "line_color" ) )
1152  {
1153  m->setOutlineColor( QColor( props["line_color"] ) );
1154  }
1155 
1156  if ( props.contains( "outline-width" ) )
1157  {
1158  //pre 2.5 projects used "outline-width"
1159  m->setOutlineWidth( props["outline-width"].toDouble() );
1160  }
1161  else if ( props.contains( "outline_width" ) )
1162  {
1163  m->setOutlineWidth( props["outline_width"].toDouble() );
1164  }
1165  else if ( props.contains( "line_width" ) )
1166  {
1167  m->setOutlineWidth( props["line_width"].toDouble() );
1168  }
1169 
1170  if ( props.contains( "outline_width_unit" ) )
1171  {
1172  m->setOutlineWidthUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["outline_width_unit"] ) );
1173  }
1174  else if ( props.contains( "line_width_unit" ) )
1175  {
1176  m->setOutlineWidthUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["line_width_unit"] ) );
1177  }
1178  if ( props.contains( "outline_width_map_unit_scale" ) )
1179  m->setOutlineWidthMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( props["outline_width_map_unit_scale"] ) );
1180 
1181  if ( props.contains( "horizontal_anchor_point" ) )
1182  {
1183  m->setHorizontalAnchorPoint( QgsMarkerSymbolLayerV2::HorizontalAnchorPoint( props[ "horizontal_anchor_point" ].toInt() ) );
1184  }
1185  if ( props.contains( "vertical_anchor_point" ) )
1186  {
1187  m->setVerticalAnchorPoint( QgsMarkerSymbolLayerV2::VerticalAnchorPoint( props[ "vertical_anchor_point" ].toInt() ) );
1188  }
1189 
1190  m->restoreDataDefinedProperties( props );
1191 
1192  return m;
1193 }
1194 
1196 {
1197  mPath = path;
1198  QColor fillColor, outlineColor;
1199  double outlineWidth;
1200  bool hasFillParam, hasOutlineParam, hasOutlineWidthParam;
1201  QgsSvgCache::instance()->containsParams( path, hasFillParam, fillColor, hasOutlineParam, outlineColor, hasOutlineWidthParam, outlineWidth );
1202  if ( hasFillParam )
1203  {
1204  setFillColor( fillColor );
1205  }
1206  if ( hasOutlineParam )
1207  {
1208  setOutlineColor( outlineColor );
1209  }
1210  if ( hasOutlineWidthParam )
1211  {
1212  setOutlineWidth( outlineWidth );
1213  }
1214 }
1215 
1216 
1218 {
1219  return "SvgMarker";
1220 }
1221 
1223 {
1224  QgsMarkerSymbolLayerV2::startRender( context ); // get anchor point expressions
1225  Q_UNUSED( context );
1226  prepareExpressions( context.fields(), context.renderContext().rendererScale() );
1227 }
1228 
1230 {
1231  Q_UNUSED( context );
1232 }
1233 
1235 {
1236  QPainter *p = context.renderContext().painter();
1237  if ( !p )
1238  return;
1239 
1240  double scaledSize = mSize;
1241 
1243 
1244  bool ok = true;
1246  {
1247  scaledSize = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_SIZE, context.feature(), mSize, &ok ).toDouble();
1248  }
1249 
1250  if ( hasDataDefinedSize && ok )
1251  {
1252  switch ( mScaleMethod )
1253  {
1255  scaledSize = sqrt( scaledSize );
1256  break;
1258  break;
1259  }
1260  }
1261 
1263 
1264  //don't render symbols with size below one or above 10,000 pixels
1265  if (( int )size < 1 || 10000.0 < size )
1266  {
1267  return;
1268  }
1269 
1270  p->save();
1271 
1272  //offset
1273  double offsetX = 0;
1274  double offsetY = 0;
1275  markerOffset( context, scaledSize, scaledSize, offsetX, offsetY );
1276  QPointF outputOffset( offsetX, offsetY );
1277 
1278  double angle = mAngle + mLineAngle;
1280  {
1282  }
1283 
1285  if ( hasDataDefinedRotation )
1286  {
1287  // For non-point markers, "dataDefinedRotation" means following the
1288  // shape (shape-data defined). For them, "field-data defined" does
1289  // not work at all. TODO: if "field-data defined" ever gets implemented
1290  // we'll need a way to distinguish here between the two, possibly
1291  // using another flag in renderHints()
1292  const QgsFeature* f = context.feature();
1293  if ( f )
1294  {
1295  const QgsGeometry *g = f->constGeometry();
1296  if ( g && g->type() == QGis::Point )
1297  {
1298  const QgsMapToPixel& m2p = context.renderContext().mapToPixel();
1299  angle += m2p.mapRotation();
1300  }
1301  }
1302  }
1303 
1304  if ( angle )
1305  outputOffset = _rotatedOffset( outputOffset, angle );
1306  p->translate( point + outputOffset );
1307 
1308  bool rotated = !qgsDoubleNear( angle, 0 );
1309  if ( rotated )
1310  p->rotate( angle );
1311 
1312  QString path = mPath;
1314  {
1315  path = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_NAME, context.feature(), mPath ).toString();
1316  }
1317 
1318  double outlineWidth = mOutlineWidth;
1320  {
1322  }
1323 
1324  QColor fillColor = mFillColor;
1326  {
1327  QString colorString = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_FILL, context.feature(), QVariant(), &ok ).toString();
1328  if ( ok )
1329  fillColor = QgsSymbolLayerV2Utils::decodeColor( colorString );
1330  }
1331 
1332  QColor outlineColor = mOutlineColor;
1334  {
1335  QString colorString = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE, context.feature(), QVariant(), &ok ).toString();
1336  if ( ok )
1337  outlineColor = QgsSymbolLayerV2Utils::decodeColor( colorString );
1338  }
1339 
1340  bool fitsInCache = true;
1341  bool usePict = true;
1342  double hwRatio = 1.0;
1343  if ( !context.renderContext().forceVectorOutput() && !rotated )
1344  {
1345  usePict = false;
1346  const QImage& img = QgsSvgCache::instance()->svgAsImage( path, size, fillColor, outlineColor, outlineWidth,
1347  context.renderContext().scaleFactor(), context.renderContext().rasterScaleFactor(), fitsInCache );
1348  if ( fitsInCache && img.width() > 1 )
1349  {
1350  //consider transparency
1351  if ( !qgsDoubleNear( context.alpha(), 1.0 ) )
1352  {
1353  QImage transparentImage = img.copy();
1354  QgsSymbolLayerV2Utils::multiplyImageOpacity( &transparentImage, context.alpha() );
1355  p->drawImage( -transparentImage.width() / 2.0, -transparentImage.height() / 2.0, transparentImage );
1356  hwRatio = ( double )transparentImage.height() / ( double )transparentImage.width();
1357  }
1358  else
1359  {
1360  p->drawImage( -img.width() / 2.0, -img.height() / 2.0, img );
1361  hwRatio = ( double )img.height() / ( double )img.width();
1362  }
1363  }
1364  }
1365 
1366  if ( usePict || !fitsInCache )
1367  {
1368  p->setOpacity( context.alpha() );
1369  const QPicture& pct = QgsSvgCache::instance()->svgAsPicture( path, size, fillColor, outlineColor, outlineWidth,
1371 
1372  if ( pct.width() > 1 )
1373  {
1374  p->save();
1375  _fixQPictureDPI( p );
1376  p->drawPicture( 0, 0, pct );
1377  p->restore();
1378  hwRatio = ( double )pct.height() / ( double )pct.width();
1379  }
1380  }
1381 
1382  if ( context.selected() )
1383  {
1384  QPen pen( context.renderContext().selectionColor() );
1386  if ( penWidth > size / 20 )
1387  {
1388  // keep the pen width from covering symbol
1389  penWidth = size / 20;
1390  }
1391  double penOffset = penWidth / 2;
1392  pen.setWidth( penWidth );
1393  p->setPen( pen );
1394  p->setBrush( Qt::NoBrush );
1395  double wSize = size + penOffset;
1396  double hSize = size * hwRatio + penOffset;
1397  p->drawRect( QRectF( -wSize / 2.0, -hSize / 2.0, wSize, hSize ) );
1398  }
1399 
1400  p->restore();
1401 }
1402 
1403 
1405 {
1406  QgsStringMap map;
1408  map["size"] = QString::number( mSize );
1409  map["size_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mSizeUnit );
1410  map["size_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mSizeMapUnitScale );
1411  map["angle"] = QString::number( mAngle );
1412  map["offset"] = QgsSymbolLayerV2Utils::encodePoint( mOffset );
1413  map["offset_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mOffsetUnit );
1414  map["offset_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOffsetMapUnitScale );
1415  map["scale_method"] = QgsSymbolLayerV2Utils::encodeScaleMethod( mScaleMethod );
1416  map["color"] = mFillColor.name();
1417  map["outline_color"] = mOutlineColor.name();
1418  map["outline_width"] = QString::number( mOutlineWidth );
1419  map["outline_width_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mOutlineWidthUnit );
1420  map["outline_width_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOutlineWidthMapUnitScale );
1421  map["horizontal_anchor_point"] = QString::number( mHorizontalAnchorPoint );
1422  map["vertical_anchor_point"] = QString::number( mVerticalAnchorPoint );
1423 
1425  return map;
1426 }
1427 
1429 {
1431  m->setFillColor( mFillColor );
1436  m->setOffset( mOffset );
1437  m->setOffsetUnit( mOffsetUnit );
1439  m->setSizeUnit( mSizeUnit );
1444  copyPaintEffect( m );
1445  return m;
1446 }
1447 
1449 {
1451  mOutlineWidthUnit = unit;
1452 }
1453 
1455 {
1457  if ( unit != mOutlineWidthUnit )
1458  {
1459  return QgsSymbolV2::Mixed;
1460  }
1461  return unit;
1462 }
1463 
1465 {
1467  mOutlineWidthMapUnitScale = scale;
1468 }
1469 
1471 {
1473  {
1475  }
1476  return QgsMapUnitScale();
1477 }
1478 
1479 void QgsSvgMarkerSymbolLayerV2::writeSldMarker( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const
1480 {
1481  // <Graphic>
1482  QDomElement graphicElem = doc.createElement( "se:Graphic" );
1483  element.appendChild( graphicElem );
1484 
1485  QgsSymbolLayerV2Utils::externalGraphicToSld( doc, graphicElem, mPath, "image/svg+xml", mFillColor, mSize );
1486 
1487  // <Rotation>
1488  QString angleFunc;
1489  bool ok;
1490  double angle = props.value( "angle", "0" ).toDouble( &ok );
1491  if ( !ok )
1492  {
1493  angleFunc = QString( "%1 + %2" ).arg( props.value( "angle", "0" ) ).arg( mAngle );
1494  }
1495  else if ( angle + mAngle != 0 )
1496  {
1497  angleFunc = QString::number( angle + mAngle );
1498  }
1499 
1500  QgsSymbolLayerV2Utils::createRotationElement( doc, graphicElem, angleFunc );
1501 
1502  // <Displacement>
1504 }
1505 
1507 {
1508  QgsDebugMsg( "Entered." );
1509 
1510  QDomElement graphicElem = element.firstChildElement( "Graphic" );
1511  if ( graphicElem.isNull() )
1512  return NULL;
1513 
1514  QString path, mimeType;
1515  QColor fillColor;
1516  double size;
1517 
1518  if ( !QgsSymbolLayerV2Utils::externalGraphicFromSld( graphicElem, path, mimeType, fillColor, size ) )
1519  return NULL;
1520 
1521  if ( mimeType != "image/svg+xml" )
1522  return NULL;
1523 
1524  double angle = 0.0;
1525  QString angleFunc;
1526  if ( QgsSymbolLayerV2Utils::rotationFromSldElement( graphicElem, angleFunc ) )
1527  {
1528  bool ok;
1529  double d = angleFunc.toDouble( &ok );
1530  if ( ok )
1531  angle = d;
1532  }
1533 
1534  QPointF offset;
1536 
1538  m->setFillColor( fillColor );
1539  //m->setOutlineColor( outlineColor );
1540  //m->setOutlineWidth( outlineWidth );
1541  m->setAngle( angle );
1542  m->setOffset( offset );
1543  return m;
1544 }
1545 
1546 bool QgsSvgMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f,
1547  const QPointF& shift ) const
1548 {
1549  Q_UNUSED( layerName );
1550  Q_UNUSED( shift ); //todo...
1551 
1552  QSvgRenderer r( mPath );
1553  if ( !r.isValid() )
1554  {
1555  return false;
1556  }
1557 
1558  QgsDxfPaintDevice pd( &e );
1559  pd.setDrawingSize( QSizeF( r.defaultSize() ) );
1560 
1561  //size
1562  double size = mSize;
1563 
1565 
1566  bool ok = true;
1568  {
1569  size = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_SIZE, f, mSize, &ok ).toDouble();
1570  }
1571 
1572  if ( hasDataDefinedSize && ok )
1573  {
1574  switch ( mScaleMethod )
1575  {
1577  size = sqrt( size );
1578  break;
1580  break;
1581  }
1582  }
1583 
1584  if ( mSizeUnit == QgsSymbolV2::MM )
1585  {
1586  size *= mmMapUnitScaleFactor;
1587  }
1588 
1589  double halfSize = size / 2.0;
1590 
1591  //offset, angle
1592  QPointF offset = mOffset;
1593 
1595  {
1596  QString offsetString = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OFFSET, f, QVariant(), &ok ).toString();
1597  if ( ok )
1598  offset = QgsSymbolLayerV2Utils::decodePoint( offsetString );
1599  }
1600  double offsetX = offset.x();
1601  double offsetY = offset.y();
1602  if ( mSizeUnit == QgsSymbolV2::MM )
1603  {
1604  offsetX *= mmMapUnitScaleFactor;
1605  offsetY *= mmMapUnitScaleFactor;
1606  }
1607 
1608  QPointF outputOffset( offsetX, offsetY );
1609 
1610  double angle = mAngle + mLineAngle;
1612  {
1614  }
1615  //angle = -angle; //rotation in Qt is counterclockwise
1616  if ( angle )
1617  outputOffset = _rotatedOffset( outputOffset, angle );
1618 
1619  QPainter p;
1620  p.begin( &pd );
1621  if ( !qgsDoubleNear( angle, 0.0 ) )
1622  {
1623  p.translate( r.defaultSize().width() / 2.0, r.defaultSize().height() / 2.0 );
1624  p.rotate( angle );
1625  p.translate( -r.defaultSize().width() / 2.0, -r.defaultSize().height() / 2.0 );
1626  }
1627  pd.setShift( shift );
1628  pd.setOutputSize( QRectF( -halfSize, -halfSize, size, size ) );
1629  pd.setLayer( layerName );
1630  r.render( &p );
1631  p.end();
1632  return true;
1633 }
1634 
1636 
1637 QgsFontMarkerSymbolLayerV2::QgsFontMarkerSymbolLayerV2( QString fontFamily, QChar chr, double pointSize, QColor color, double angle )
1638  : mFontMetrics( 0 )
1639 {
1641  mChr = chr;
1642  mColor = color;
1643  mAngle = angle;
1644  mSize = pointSize;
1645  mOrigSize = pointSize;
1647  mOffset = QPointF( 0, 0 );
1649 }
1650 
1652 {
1653  delete mFontMetrics;
1654 }
1655 
1657 {
1659  QChar chr = DEFAULT_FONTMARKER_CHR;
1660  double pointSize = DEFAULT_FONTMARKER_SIZE;
1663 
1664  if ( props.contains( "font" ) )
1665  fontFamily = props["font"];
1666  if ( props.contains( "chr" ) && props["chr"].length() > 0 )
1667  chr = props["chr"].at( 0 );
1668  if ( props.contains( "size" ) )
1669  pointSize = props["size"].toDouble();
1670  if ( props.contains( "color" ) )
1671  color = QgsSymbolLayerV2Utils::decodeColor( props["color"] );
1672  if ( props.contains( "angle" ) )
1673  angle = props["angle"].toDouble();
1674 
1675  QgsFontMarkerSymbolLayerV2* m = new QgsFontMarkerSymbolLayerV2( fontFamily, chr, pointSize, color, angle );
1676  if ( props.contains( "offset" ) )
1677  m->setOffset( QgsSymbolLayerV2Utils::decodePoint( props["offset"] ) );
1678  if ( props.contains( "offset_unit" ) )
1679  m->setOffsetUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["offset_unit" ] ) );
1680  if ( props.contains( "offset_map_unit_scale" ) )
1681  m->setOffsetMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( props["offset_map_unit_scale" ] ) );
1682  if ( props.contains( "size_unit" ) )
1683  m->setSizeUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["size_unit"] ) );
1684  if ( props.contains( "size_map_unit_scale" ) )
1685  m->setSizeMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( props["size_map_unit_scale"] ) );
1686  if ( props.contains( "horizontal_anchor_point" ) )
1687  {
1688  m->setHorizontalAnchorPoint( QgsMarkerSymbolLayerV2::HorizontalAnchorPoint( props[ "horizontal_anchor_point" ].toInt() ) );
1689  }
1690  if ( props.contains( "vertical_anchor_point" ) )
1691  {
1692  m->setVerticalAnchorPoint( QgsMarkerSymbolLayerV2::VerticalAnchorPoint( props[ "vertical_anchor_point" ].toInt() ) );
1693  }
1694 
1695  m->restoreDataDefinedProperties( props );
1696 
1697  return m;
1698 }
1699 
1701 {
1702  return "FontMarker";
1703 }
1704 
1706 {
1707  mFont = QFont( mFontFamily );
1709  delete mFontMetrics;
1710  mFontMetrics = new QFontMetrics( mFont );
1711  mChrOffset = QPointF( mFontMetrics->width( mChr ) / 2.0, -mFontMetrics->ascent() / 2.0 );
1712  mOrigSize = mSize; // save in case the size would be data defined
1713  prepareExpressions( context.fields(), context.renderContext().rendererScale() );
1714 }
1715 
1717 {
1718  Q_UNUSED( context );
1719 }
1720 
1722 {
1723  QPainter *p = context.renderContext().painter();
1724  if ( !p )
1725  return;
1726 
1727  QColor penColor = mColor;
1728  bool ok;
1730  {
1731  QString colorString = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_COLOR, context.feature(), QVariant(), &ok ).toString();
1732  if ( ok )
1733  penColor = QgsSymbolLayerV2Utils::decodeColor( colorString );
1734  }
1735  penColor = context.selected() ? context.renderContext().selectionColor() : penColor;
1736  penColor.setAlphaF( penColor.alphaF() * context.alpha() );
1737 
1738  p->setPen( penColor );
1739  p->setFont( mFont );
1740 
1741  p->save();
1742 
1743  QPointF chrOffset = mChrOffset;
1744  QString charToRender = mChr;
1746  {
1747  charToRender = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_CHAR, context.feature(), mChr ).toString();
1748  if ( charToRender != mChr )
1749  {
1750  chrOffset = QPointF( mFontMetrics->width( charToRender ) / 2.0, -mFontMetrics->ascent() / 2.0 );
1751  }
1752  }
1753 
1754  double scaledSize = mSize;
1755 
1757 
1758  ok = true;
1760  {
1761  scaledSize = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_SIZE, context.feature(), mSize, &ok ).toDouble();
1762  }
1763 
1764  if ( hasDataDefinedSize && ok )
1765  {
1766  switch ( mScaleMethod )
1767  {
1769  scaledSize = sqrt( scaledSize );
1770  break;
1772  break;
1773  }
1774  }
1775 
1776  //offset
1777  double offsetX = 0;
1778  double offsetY = 0;
1779  markerOffset( context, scaledSize, scaledSize , offsetX, offsetY );
1780  QPointF outputOffset( offsetX, offsetY );
1781 
1782  double angle = mAngle + mLineAngle;
1784  {
1786  }
1787 
1789  if ( hasDataDefinedRotation )
1790  {
1791  // For non-point markers, "dataDefinedRotation" means following the
1792  // shape (shape-data defined). For them, "field-data defined" does
1793  // not work at all. TODO: if "field-data defined" ever gets implemented
1794  // we'll need a way to distinguish here between the two, possibly
1795  // using another flag in renderHints()
1796  const QgsFeature* f = context.feature();
1797  if ( f )
1798  {
1799  const QgsGeometry *g = f->constGeometry();
1800  if ( g && g->type() == QGis::Point )
1801  {
1802  const QgsMapToPixel& m2p = context.renderContext().mapToPixel();
1803  angle += m2p.mapRotation();
1804  }
1805  }
1806  }
1807 
1808  if ( angle )
1809  outputOffset = _rotatedOffset( outputOffset, angle );
1810  p->translate( point + outputOffset );
1811 
1812  if ( !qgsDoubleNear( scaledSize, mOrigSize ) )
1813  {
1814  double s = scaledSize / mOrigSize;
1815  p->scale( s, s );
1816  }
1817 
1818  bool rotated = !qgsDoubleNear( angle, 0 );
1819  if ( rotated )
1820  p->rotate( angle );
1821 
1822  p->drawText( -chrOffset, charToRender );
1823  p->restore();
1824 }
1825 
1827 {
1828  QgsStringMap props;
1829  props["font"] = mFontFamily;
1830  props["chr"] = mChr;
1831  props["size"] = QString::number( mSize );
1832  props["size_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mSizeUnit );
1833  props["size_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mSizeMapUnitScale );
1834  props["color"] = QgsSymbolLayerV2Utils::encodeColor( mColor );
1835  props["angle"] = QString::number( mAngle );
1836  props["offset"] = QgsSymbolLayerV2Utils::encodePoint( mOffset );
1837  props["offset_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mOffsetUnit );
1838  props["offset_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOffsetMapUnitScale );
1839  props["horizontal_anchor_point"] = QString::number( mHorizontalAnchorPoint );
1840  props["vertical_anchor_point"] = QString::number( mVerticalAnchorPoint );
1841 
1842  //data define properties
1843  saveDataDefinedProperties( props );
1844 
1845  return props;
1846 }
1847 
1849 {
1851  m->setOffset( mOffset );
1852  m->setOffsetUnit( mOffsetUnit );
1854  m->setSizeUnit( mSizeUnit );
1859  copyPaintEffect( m );
1860  return m;
1861 }
1862 
1863 void QgsFontMarkerSymbolLayerV2::writeSldMarker( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const
1864 {
1865  // <Graphic>
1866  QDomElement graphicElem = doc.createElement( "se:Graphic" );
1867  element.appendChild( graphicElem );
1868 
1869  QString fontPath = QString( "ttf://%1" ).arg( mFontFamily );
1870  int markIndex = mChr.unicode();
1871  QgsSymbolLayerV2Utils::externalMarkerToSld( doc, graphicElem, fontPath, "ttf", &markIndex, mColor, mSize );
1872 
1873  // <Rotation>
1874  QString angleFunc;
1875  bool ok;
1876  double angle = props.value( "angle", "0" ).toDouble( &ok );
1877  if ( !ok )
1878  {
1879  angleFunc = QString( "%1 + %2" ).arg( props.value( "angle", "0" ) ).arg( mAngle );
1880  }
1881  else if ( angle + mAngle != 0 )
1882  {
1883  angleFunc = QString::number( angle + mAngle );
1884  }
1885  QgsSymbolLayerV2Utils::createRotationElement( doc, graphicElem, angleFunc );
1886 
1887  // <Displacement>
1889 }
1890 
1892 {
1893  QgsDebugMsg( "Entered." );
1894 
1895  QDomElement graphicElem = element.firstChildElement( "Graphic" );
1896  if ( graphicElem.isNull() )
1897  return NULL;
1898 
1899  QString name, format;
1900  QColor color;
1901  double size;
1902  int chr;
1903 
1904  if ( !QgsSymbolLayerV2Utils::externalMarkerFromSld( graphicElem, name, format, chr, color, size ) )
1905  return NULL;
1906 
1907  if ( !name.startsWith( "ttf://" ) || format != "ttf" )
1908  return NULL;
1909 
1910  QString fontFamily = name.mid( 6 );
1911 
1912  double angle = 0.0;
1913  QString angleFunc;
1914  if ( QgsSymbolLayerV2Utils::rotationFromSldElement( graphicElem, angleFunc ) )
1915  {
1916  bool ok;
1917  double d = angleFunc.toDouble( &ok );
1918  if ( ok )
1919  angle = d;
1920  }
1921 
1922  QPointF offset;
1924 
1925  QgsMarkerSymbolLayerV2 *m = new QgsFontMarkerSymbolLayerV2( fontFamily, chr, size, color );
1926  m->setAngle( angle );
1927  m->setOffset( offset );
1928  return m;
1929 }
1930 
1931 
QgsSymbolV2::OutputUnit outputUnit() const override
static QString encodeOutputUnit(QgsSymbolV2::OutputUnit unit)
Q_GUI_EXPORT int qt_defaultDpiX()
static const QString EXPR_CHAR
void setOutlineStyle(Qt::PenStyle outlineStyle)
void stopRender(QgsSymbolV2RenderContext &context) override
QgsSymbolV2::OutputUnit outputUnit() const override
static void multiplyImageOpacity(QImage *image, qreal alpha)
Multiplies opacity of image pixel values with a (global) transparency value.
int renderHints() const
Definition: qgssymbolv2.h:238
QgsMapUnitScale mSizeMapUnitScale
Q_GUI_EXPORT int qt_defaultDpiY()
QString layerType() const override
QgsStringMap properties() const override
static Q_DECL_DEPRECATED bool wellKnownMarkerFromSld(QDomElement &element, QString &name, QColor &color, QColor &borderColor, double &borderWidth, double &size)
A paint device for drawing into dxf files.
QString layerType() const override
#define DEFAULT_FONTMARKER_COLOR
const QPicture & svgAsPicture(const QString &file, double size, const QColor &fill, const QColor &outline, double outlineWidth, double widthScaleFactor, double rasterScaleFactor, bool forceVectorOutput=false)
Get SVG as QPicture&.
QColor selectionColor() const
QgsSymbolLayerV2 * clone() const override
QgsSymbolV2::OutputUnit mOutlineWidthUnit
void setOutlineColor(const QColor &c) override
Set outline color.
QString layerType() const override
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
#define DEFAULT_SIMPLEMARKER_ANGLE
static void createRotationElement(QDomDocument &doc, QDomElement &element, QString rotationFunc)
double rendererScale() const
#define DEFAULT_FONTMARKER_CHR
void writeSolid(const QString &layer, QColor color, const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, const QgsPoint &pt4)
void setOffset(QPointF offset)
QString ogrFeatureStyle(double mmScaleFactor, double mapUnitScaleFactor) const override
void setHorizontalAnchorPoint(HorizontalAnchorPoint h)
#define DEG2RAD(x)
#define DEFAULT_SIMPLEMARKER_COLOR
void writeSldMarker(QDomDocument &doc, QDomElement &element, QgsStringMap props) const override
QgsSymbolLayerV2 * clone() const override
static QPointF decodePoint(QString str)
void setVerticalAnchorPoint(VerticalAnchorPoint v)
static bool externalGraphicFromSld(QDomElement &element, QString &path, QString &mime, QColor &color, double &size)
static QColor decodeColor(QString str)
void copyPaintEffect(QgsSymbolLayerV2 *destLayer) const
Copies paint effect of this layer to another symbol layer.
void stopRender(QgsSymbolV2RenderContext &context) override
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
virtual bool hasDataDefinedProperty(const QString &property) const
Checks whether the layer has a matching data defined property and if that property is currently activ...
double scaleFactor() const
QColor fillColor() const override
Get fill color.
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:119
static void _fixQPictureDPI(QPainter *p)
void setOffsetMapUnitScale(const QgsMapUnitScale &scale)
static void createDisplacementElement(QDomDocument &doc, QDomElement &element, QPointF offset)
void writeSldMarker(QDomDocument &doc, QDomElement &element, QgsStringMap props) const override
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
QMap< QString, QString > QgsStringMap
Definition: qgis.h:438
QgsSymbolLayerV2 * clone() const override
double mapRotation() const
Return current map rotation in degrees.
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Definition: qgis.h:347
static const QString EXPR_OFFSET
void setMapUnitScale(const QgsMapUnitScale &scale) override
static QgsSymbolLayerV2 * createFromSld(QDomElement &element)
void writeCircle(const QString &layer, QColor color, const QgsPoint &pt, double radius, const QString &lineStyleName, double width)
#define DEFAULT_SVGMARKER_ANGLE
static const QString EXPR_SIZE
void setOffsetUnit(QgsSymbolV2::OutputUnit unit)
static QString encodeColor(QColor color)
#define DEFAULT_SIMPLEMARKER_NAME
void containsParams(const QString &path, bool &hasFillParam, QColor &defaultFillColor, bool &hasOutlineParam, QColor &defaultOutlineColor, bool &hasOutlineWidthParam, double &defaultOutlineWidth) const
Tests if an svg file contains parameters for fill, outline color, outline width.
static bool displacementFromSldElement(QDomElement &element, QPointF &offset)
qreal alpha() const
Get alpha transparency 1 for opaque, 0 for invisible.
Definition: qgssymbolv2.h:231
void drawMarker(QPainter *p, QgsSymbolV2RenderContext &context)
static QgsSvgCache * instance()
Definition: qgssvgcache.cpp:84
static QString encodePenStyle(Qt::PenStyle style)
void setOutlineWidthUnit(QgsSymbolV2::OutputUnit unit)
bool writeDxf(QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, const QgsSymbolV2RenderContext *context, const QgsFeature *f, const QPointF &shift=QPointF(0.0, 0.0)) const override
const QImage & svgAsImage(const QString &file, double size, const QColor &fill, const QColor &outline, double outlineWidth, double widthScaleFactor, double rasterScaleFactor, bool &fitsInCache)
Get SVG as QImage.
QgsFontMarkerSymbolLayerV2(QString fontFamily=DEFAULT_FONTMARKER_FONT, QChar chr=DEFAULT_FONTMARKER_CHR, double pointSize=DEFAULT_FONTMARKER_SIZE, QColor color=DEFAULT_FONTMARKER_COLOR, double angle=DEFAULT_FONTMARKER_ANGLE)
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:34
static QString symbolPathToName(QString path)
Get symbols's name from its path.
void setMapUnitScale(const QgsMapUnitScale &scale) override
void setOutlineWidthUnit(QgsSymbolV2::OutputUnit u)
const QgsFeature * feature() const
Current feature being rendered - may be null.
Definition: qgssymbolv2.h:243
static QString encodePoint(QPointF point)
QgsStringMap properties() const override
static Qt::PenStyle decodePenStyle(QString str)
void renderPoint(const QPointF &point, QgsSymbolV2RenderContext &context) override
#define DEFAULT_SCALE_METHOD
void setOutputUnit(QgsSymbolV2::OutputUnit unit) override
void setMapUnitScale(const QgsMapUnitScale &scale) override
QgsSymbolV2::ScaleMethod mScaleMethod
static QString symbolNameToPath(QString name)
Get symbol's path from its name.
bool forceVectorOutput() const
void setLayer(const QString &layer)
void setSizeUnit(QgsSymbolV2::OutputUnit unit)
static bool externalMarkerFromSld(QDomElement &element, QString &path, QString &format, int &markIndex, QColor &color, double &size)
QgsMapUnitScale mapUnitScale() const override
QgsStringMap properties() const override
void stopRender(QgsSymbolV2RenderContext &context) override
double rasterScaleFactor() const
#define DEFAULT_FONTMARKER_ANGLE
QgsSymbolV2::OutputUnit outputUnit() const override
void writeLine(const QgsPoint &pt1, const QgsPoint &pt2, const QString &layer, const QString &lineStyleName, QColor color, double width=-1)
write line (as a polyline)
static const QString EXPR_FILL
virtual QColor color() const
QgsSvgMarkerSymbolLayerV2(QString name=DEFAULT_SVGMARKER_NAME, double size=DEFAULT_SVGMARKER_SIZE, double angle=DEFAULT_SVGMARKER_ANGLE, QgsSymbolV2::ScaleMethod scaleMethod=DEFAULT_SCALE_METHOD)
static QgsSymbolLayerV2 * createFromSld(QDomElement &element)
HorizontalAnchorPoint mHorizontalAnchorPoint
virtual void prepareExpressions(const QgsFields *fields, double scale=-1.0)
Prepares all data defined property expressions for evaluation.
void setOutlineWidthMapUnitScale(const QgsMapUnitScale &scale)
QgsSymbolV2::ScaleMethod scaleMethod() const
static const QString EXPR_OUTLINE_STYLE
QgsSymbolV2::OutputUnit mOutlineWidthUnit
#define DEFAULT_SVGMARKER_SIZE
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)
static const QString EXPR_COLOR
static const QString EXPR_ANGLE
void setOutlineWidthMapUnitScale(const QgsMapUnitScale &scale)
QgsMapUnitScale mapUnitScale() const override
void startRender(QgsSymbolV2RenderContext &context) override
#define DEFAULT_FONTMARKER_SIZE
void startRender(QgsSymbolV2RenderContext &context) override
static const QString EXPR_OUTLINE_WIDTH
#define DEFAULT_FONTMARKER_FONT
#define DEFAULT_SVGMARKER_NAME
#define DEFAULT_SIMPLEMARKER_SIZE
QPainter * painter()
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.
void renderPoint(const QPointF &point, QgsSymbolV2RenderContext &context) override
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
virtual QVariant evaluateDataDefinedProperty(const QString &property, const QgsFeature *feature, const QVariant &defaultVal=QVariant(), bool *ok=0) const
Evaluates the matching data defined property and returns the calculated value.
void setOutputUnit(QgsSymbolV2::OutputUnit unit) override
QgsMapUnitScale mapUnitScale() const override
Qt::PenStyle outlineStyle() const
static const QString EXPR_NAME
void setShift(const QPointF &shift)
QgsSimpleMarkerSymbolLayerV2(QString name=DEFAULT_SIMPLEMARKER_NAME, QColor color=DEFAULT_SIMPLEMARKER_COLOR, QColor borderColor=DEFAULT_SIMPLEMARKER_BORDERCOLOR, double size=DEFAULT_SIMPLEMARKER_SIZE, double angle=DEFAULT_SIMPLEMARKER_ANGLE, QgsSymbolV2::ScaleMethod scaleMethod=DEFAULT_SCALE_METHOD)
static QString encodeScaleMethod(QgsSymbolV2::ScaleMethod scaleMethod)
QgsRenderContext & renderContext()
Definition: qgssymbolv2.h:221
bool preparePath(QString name=QString())
void writeFilledCircle(const QString &layer, QColor color, const QgsPoint &pt, double radius)
static const QString EXPR_COLOR_BORDER
static void externalGraphicToSld(QDomDocument &doc, QDomElement &element, QString path, QString mime, QColor color, double size=-1)
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
Definition: qgsfeature.cpp:68
bool writeDxf(QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, const QgsSymbolV2RenderContext *context, const QgsFeature *f, const QPointF &shift=QPointF(0.0, 0.0)) const override
static Q_DECL_DEPRECATED void wellKnownMarkerToSld(QDomDocument &doc, QDomElement &element, QString name, QColor color, QColor borderColor=QColor(), double borderWidth=-1, double size=-1)
const QgsMapToPixel & mapToPixel() const
const QgsFields * fields() const
Fields of the layer.
Definition: qgssymbolv2.h:249
QgsSymbolV2::OutputUnit mOffsetUnit
void startRender(QgsSymbolV2RenderContext &context) override
static bool rotationFromSldElement(QDomElement &element, QString &rotationFunc)
bool selected() const
Definition: qgssymbolv2.h:235
static QgsSymbolV2::ScaleMethod decodeScaleMethod(QString str)
void startRender(QgsSymbolV2RenderContext &context) override
VerticalAnchorPoint mVerticalAnchorPoint
bool prepareShape(QString name=QString())
QgsSymbolV2::OutputUnit mSizeUnit
void setDrawingSize(const QSizeF &size)
QgsMapUnitScale mOffsetMapUnitScale
static const QString EXPR_OUTLINE
void markerOffset(const QgsSymbolV2RenderContext &context, double &offsetX, double &offsetY) const
void restoreDataDefinedProperties(const QgsStringMap &stringMap)
Restores all data defined properties from string map.
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
void writeSldMarker(QDomDocument &doc, QDomElement &element, QgsStringMap props) const override
void setAngle(double angle)
QPointF offset() const
double size
Definition: qgssvgcache.cpp:77
static QgsSymbolLayerV2 * createFromSld(QDomElement &element)
void saveDataDefinedProperties(QgsStringMap &stringMap) const
Saves all data defined properties to a string map.
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
QColor outlineColor() const override
Get outline color.
void setOutputUnit(QgsSymbolV2::OutputUnit unit) override
bool prepareCache(QgsSymbolV2RenderContext &context)
Prepares cache image.
static QgsSymbolV2::OutputUnit decodeOutputUnit(QString str)
void renderPoint(const QPointF &point, QgsSymbolV2RenderContext &context) override
static void externalMarkerToSld(QDomDocument &doc, QDomElement &element, QString path, QString format, int *markIndex=0, QColor color=QColor(), double size=-1)
void copyDataDefinedProperties(QgsSymbolLayerV2 *destLayer) const
Copies all data defined properties of this layer to another symbol layer.
void setFillColor(const QColor &c) override
Set fill color.
void setOutputSize(const QRectF &r)
static QPointF _rotatedOffset(const QPointF &offset, double angle)
#define DEFAULT_SIMPLEMARKER_BORDERCOLOR