QGIS API Documentation  2.4.0-Chugiak
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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  mAngleExpression = NULL;
63  mNameExpression = NULL;
64 }
65 
67 {
74 
75  if ( props.contains( "name" ) )
76  name = props["name"];
77  if ( props.contains( "color" ) )
78  color = QgsSymbolLayerV2Utils::decodeColor( props["color"] );
79  if ( props.contains( "color_border" ) )
80  borderColor = QgsSymbolLayerV2Utils::decodeColor( props["color_border"] );
81  if ( props.contains( "size" ) )
82  size = props["size"].toDouble();
83  if ( props.contains( "angle" ) )
84  angle = props["angle"].toDouble();
85  if ( props.contains( "scale_method" ) )
86  scaleMethod = QgsSymbolLayerV2Utils::decodeScaleMethod( props["scale_method"] );
87 
88  QgsSimpleMarkerSymbolLayerV2* m = new QgsSimpleMarkerSymbolLayerV2( name, color, borderColor, size, angle, scaleMethod );
89  if ( props.contains( "offset" ) )
90  m->setOffset( QgsSymbolLayerV2Utils::decodePoint( props["offset"] ) );
91  if ( props.contains( "offset_unit" ) )
92  m->setOffsetUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["offset_unit"] ) );
93  if ( props.contains( "offset_map_unit_scale" ) )
94  m->setOffsetMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( props["offset_map_unit_scale"] ) );
95  if ( props.contains( "size_unit" ) )
96  m->setSizeUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["size_unit"] ) );
97  if ( props.contains( "size_map_unit_scale" ) )
98  m->setSizeMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( props["size_map_unit_scale"] ) );
99 
100  if ( props.contains( "outline_style" ) )
101  {
102  m->setOutlineStyle( QgsSymbolLayerV2Utils::decodePenStyle( props["outline_style"] ) );
103  }
104  if ( props.contains( "outline_width" ) )
105  {
106  m->setOutlineWidth( props["outline_width"].toDouble() );
107  }
108  if ( props.contains( "outline_width_unit" ) )
109  {
110  m->setOutlineWidthUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["outline_width_unit"] ) );
111  }
112  if ( props.contains( "outline_width_map_unit_scale" ) )
113  {
114  m->setOutlineWidthMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( props["outline_width_map_unit_scale"] ) );
115  }
116 
117  if ( props.contains( "horizontal_anchor_point" ) )
118  {
119  m->setHorizontalAnchorPoint( QgsMarkerSymbolLayerV2::HorizontalAnchorPoint( props[ "horizontal_anchor_point" ].toInt() ) );
120  }
121  if ( props.contains( "vertical_anchor_point" ) )
122  {
123  m->setVerticalAnchorPoint( QgsMarkerSymbolLayerV2::VerticalAnchorPoint( props[ "vertical_anchor_point" ].toInt() ) );
124  }
125 
126  //data defined properties
127  if ( props.contains( "name_expression" ) )
128  {
129  m->setDataDefinedProperty( "name", props["name_expression"] );
130  }
131  if ( props.contains( "color_expression" ) )
132  {
133  m->setDataDefinedProperty( "color", props["color_expression"] );
134  }
135  if ( props.contains( "color_border_expression" ) )
136  {
137  m->setDataDefinedProperty( "color_border", props["color_border_expression"] );
138  }
139  if ( props.contains( "outline_width_expression" ) )
140  {
141  m->setDataDefinedProperty( "outline_width", props["outline_width_expression"] );
142  }
143  if ( props.contains( "size_expression" ) )
144  {
145  m->setDataDefinedProperty( "size", props["size_expression"] );
146  }
147  if ( props.contains( "angle_expression" ) )
148  {
149  m->setDataDefinedProperty( "angle", props["angle_expression"] );
150  }
151  if ( props.contains( "offset_expression" ) )
152  {
153  m->setDataDefinedProperty( "offset", props["offset_expression"] );
154  }
155  if ( props.contains( "horizontal_anchor_point_expression" ) )
156  {
157  m->setDataDefinedProperty( "horizontal_anchor_point", props[ "horizontal_anchor_point_expression" ] );
158  }
159  if ( props.contains( "vertical_anchor_point_expression" ) )
160  {
161  m->setDataDefinedProperty( "vertical_anchor_point", props[ "vertical_anchor_point_expression" ] );
162  }
163  return m;
164 }
165 
166 
168 {
169  return "SimpleMarker";
170 }
171 
173 {
174  QColor brushColor = mColor;
175  QColor penColor = mBorderColor;
176 
177  brushColor.setAlphaF( mColor.alphaF() * context.alpha() );
178  penColor.setAlphaF( mBorderColor.alphaF() * context.alpha() );
179 
180  mBrush = QBrush( brushColor );
181  mPen = QPen( penColor );
182  mPen.setStyle( mOutlineStyle );
184 
185  QColor selBrushColor = context.renderContext().selectionColor();
186  QColor selPenColor = selBrushColor == mColor ? selBrushColor : mBorderColor;
187  if ( context.alpha() < 1 )
188  {
189  selBrushColor.setAlphaF( context.alpha() );
190  selPenColor.setAlphaF( context.alpha() );
191  }
192  mSelBrush = QBrush( selBrushColor );
193  mSelPen = QPen( selPenColor );
194  mSelPen.setStyle( mOutlineStyle );
196 
197  bool hasDataDefinedRotation = context.renderHints() & QgsSymbolV2::DataDefinedRotation || dataDefinedProperty( "angle" );
198  bool hasDataDefinedSize = context.renderHints() & QgsSymbolV2::DataDefinedSizeScale || dataDefinedProperty( "size" );
199 
200  // use caching only when:
201  // - size, rotation, shape, color, border color is not data-defined
202  // - drawing to screen (not printer)
203  mUsingCache = !hasDataDefinedRotation && !hasDataDefinedSize && !context.renderContext().forceVectorOutput()
204  && !dataDefinedProperty( "name" ) && !dataDefinedProperty( "color" ) && !dataDefinedProperty( "color_border" ) && !dataDefinedProperty( "outline_width" ) &&
205  !dataDefinedProperty( "size" );
206 
207  // use either QPolygonF or QPainterPath for drawing
208  // TODO: find out whether drawing directly doesn't bring overhead - if not, use it for all shapes
209  if ( !prepareShape() ) // drawing as a polygon
210  {
211  if ( preparePath() ) // drawing as a painter path
212  {
213  // some markers can't be drawn as a polygon (circle, cross)
214  // For these set the selected border color to the selected color
215 
216  if ( mName != "circle" )
217  mSelPen.setColor( selBrushColor );
218  }
219  else
220  {
221  QgsDebugMsg( "unknown symbol" );
222  return;
223  }
224  }
225 
226  QMatrix transform;
227 
228  // scale the shape (if the size is not going to be modified)
229  if ( !hasDataDefinedSize )
230  {
232  if ( mUsingCache )
233  scaledSize *= context.renderContext().rasterScaleFactor();
234  double half = scaledSize / 2.0;
235  transform.scale( half, half );
236  }
237 
238  // rotate if the rotation is not going to be changed during the rendering
239  if ( !hasDataDefinedRotation && mAngle != 0 )
240  {
241  transform.rotate( mAngle );
242  }
243 
244  if ( !mPolygon.isEmpty() )
245  mPolygon = transform.map( mPolygon );
246  else
247  mPath = transform.map( mPath );
248 
249  if ( mUsingCache )
250  {
251  if ( !prepareCache( context ) )
252  {
253  mUsingCache = false;
254  }
255  }
256  else
257  {
258  mCache = QImage();
259  mSelCache = QImage();
260  }
261 
262  prepareExpressions( context.fields(), context.renderContext().rendererScale() );
263  mAngleExpression = expression( "angle" );
264  mNameExpression = expression( "name" );
265 
267 }
268 
269 
271 {
273 
274  // calculate necessary image size for the cache
275  double pw = (( mPen.widthF() == 0 ? 1 : mPen.widthF() ) + 1 ) / 2 * 2; // make even (round up); handle cosmetic pen
276  int imageSize = (( int ) scaledSize + pw ) / 2 * 2 + 1; // make image width, height odd; account for pen width
277  double center = imageSize / 2.0;
278 
279  if ( imageSize > mMaximumCacheWidth )
280  {
281  return false;
282  }
283 
284  mCache = QImage( QSize( imageSize, imageSize ), QImage::Format_ARGB32_Premultiplied );
285  mCache.fill( 0 );
286 
287  QPainter p;
288  p.begin( &mCache );
289  p.setRenderHint( QPainter::Antialiasing );
290  p.setBrush( mBrush );
291  p.setPen( mPen );
292  p.translate( QPointF( center, center ) );
293  drawMarker( &p, context );
294  p.end();
295 
296  // Construct the selected version of the Cache
297 
298  QColor selColor = context.renderContext().selectionColor();
299 
300  mSelCache = QImage( QSize( imageSize, imageSize ), QImage::Format_ARGB32_Premultiplied );
301  mSelCache.fill( 0 );
302 
303  p.begin( &mSelCache );
304  p.setRenderHint( QPainter::Antialiasing );
305  p.setBrush( mSelBrush );
306  p.setPen( mSelPen );
307  p.translate( QPointF( center, center ) );
308  drawMarker( &p, context );
309  p.end();
310 
311  // Check that the selected version is different. If not, then re-render,
312  // filling the background with the selection color and using the normal
313  // colors for the symbol .. could be ugly!
314 
315  if ( mSelCache == mCache )
316  {
317  p.begin( &mSelCache );
318  p.setRenderHint( QPainter::Antialiasing );
319  p.fillRect( 0, 0, imageSize, imageSize, selColor );
320  p.setBrush( mBrush );
321  p.setPen( mPen );
322  p.translate( QPointF( center, center ) );
323  drawMarker( &p, context );
324  p.end();
325  }
326 
327  return true;
328 }
329 
331 {
332  Q_UNUSED( context );
333 }
334 
336 {
337  mPolygon.clear();
338 
339  if ( name.isNull() )
340  {
341  name = mName;
342  }
343 
344  if ( name == "square" || name == "rectangle" )
345  {
346  mPolygon = QPolygonF( QRectF( QPointF( -1, -1 ), QPointF( 1, 1 ) ) );
347  return true;
348  }
349  else if ( name == "diamond" )
350  {
351  mPolygon << QPointF( -1, 0 ) << QPointF( 0, 1 )
352  << QPointF( 1, 0 ) << QPointF( 0, -1 );
353  return true;
354  }
355  else if ( name == "pentagon" )
356  {
357  mPolygon << QPointF( sin( DEG2RAD( 288.0 ) ), - cos( DEG2RAD( 288.0 ) ) )
358  << QPointF( sin( DEG2RAD( 216.0 ) ), - cos( DEG2RAD( 216.0 ) ) )
359  << QPointF( sin( DEG2RAD( 144.0 ) ), - cos( DEG2RAD( 144.0 ) ) )
360  << QPointF( sin( DEG2RAD( 72.0 ) ), - cos( DEG2RAD( 72.0 ) ) )
361  << QPointF( 0, -1 );
362  return true;
363  }
364  else if ( name == "triangle" )
365  {
366  mPolygon << QPointF( -1, 1 ) << QPointF( 1, 1 ) << QPointF( 0, -1 );
367  return true;
368  }
369  else if ( name == "equilateral_triangle" )
370  {
371  mPolygon << QPointF( sin( DEG2RAD( 240.0 ) ), - cos( DEG2RAD( 240.0 ) ) )
372  << QPointF( sin( DEG2RAD( 120.0 ) ), - cos( DEG2RAD( 120.0 ) ) )
373  << QPointF( 0, -1 );
374  return true;
375  }
376  else if ( name == "star" )
377  {
378  double sixth = 1.0 / 3;
379 
380  mPolygon << QPointF( 0, -1 )
381  << QPointF( -sixth, -sixth )
382  << QPointF( -1, -sixth )
383  << QPointF( -sixth, 0 )
384  << QPointF( -1, 1 )
385  << QPointF( 0, + sixth )
386  << QPointF( 1, 1 )
387  << QPointF( + sixth, 0 )
388  << QPointF( 1, -sixth )
389  << QPointF( + sixth, -sixth );
390  return true;
391  }
392  else if ( name == "regular_star" )
393  {
394  double inner_r = cos( DEG2RAD( 72.0 ) ) / cos( DEG2RAD( 36.0 ) );
395 
396  mPolygon << QPointF( inner_r * sin( DEG2RAD( 324.0 ) ), - inner_r * cos( DEG2RAD( 324.0 ) ) ) // 324
397  << QPointF( sin( DEG2RAD( 288.0 ) ) , - cos( DEG2RAD( 288 ) ) ) // 288
398  << QPointF( inner_r * sin( DEG2RAD( 252.0 ) ), - inner_r * cos( DEG2RAD( 252.0 ) ) ) // 252
399  << QPointF( sin( DEG2RAD( 216.0 ) ) , - cos( DEG2RAD( 216.0 ) ) ) // 216
400  << QPointF( 0, inner_r ) // 180
401  << QPointF( sin( DEG2RAD( 144.0 ) ) , - cos( DEG2RAD( 144.0 ) ) ) // 144
402  << QPointF( inner_r * sin( DEG2RAD( 108.0 ) ), - inner_r * cos( DEG2RAD( 108.0 ) ) ) // 108
403  << QPointF( sin( DEG2RAD( 72.0 ) ) , - cos( DEG2RAD( 72.0 ) ) ) // 72
404  << QPointF( inner_r * sin( DEG2RAD( 36.0 ) ), - inner_r * cos( DEG2RAD( 36.0 ) ) ) // 36
405  << QPointF( 0, -1 ); // 0
406  return true;
407  }
408  else if ( name == "arrow" )
409  {
410  mPolygon
411  << QPointF( 0, -1 )
412  << QPointF( 0.5, -0.5 )
413  << QPointF( 0.25, -0.5 )
414  << QPointF( 0.25, 1 )
415  << QPointF( -0.25, 1 )
416  << QPointF( -0.25, -0.5 )
417  << QPointF( -0.5, -0.5 );
418  return true;
419  }
420  else if ( name == "filled_arrowhead" )
421  {
422  mPolygon << QPointF( 0, 0 ) << QPointF( -1, 1 ) << QPointF( -1, -1 );
423  return true;
424  }
425 
426  return false;
427 }
428 
430 {
431  mPath = QPainterPath();
432  if ( name.isNull() )
433  {
434  name = mName;
435  }
436 
437  if ( name == "circle" )
438  {
439  mPath.addEllipse( QRectF( -1, -1, 2, 2 ) ); // x,y,w,h
440  return true;
441  }
442  else if ( name == "cross" )
443  {
444  mPath.moveTo( -1, 0 );
445  mPath.lineTo( 1, 0 ); // horizontal
446  mPath.moveTo( 0, -1 );
447  mPath.lineTo( 0, 1 ); // vertical
448  return true;
449  }
450  else if ( name == "x" || name == "cross2" )
451  {
452  mPath.moveTo( -1, -1 );
453  mPath.lineTo( 1, 1 );
454  mPath.moveTo( 1, -1 );
455  mPath.lineTo( -1, 1 );
456  return true;
457  }
458  else if ( name == "line" )
459  {
460  mPath.moveTo( 0, -1 );
461  mPath.lineTo( 0, 1 ); // vertical line
462  return true;
463  }
464  else if ( name == "arrowhead" )
465  {
466  mPath.moveTo( 0, 0 );
467  mPath.lineTo( -1, -1 );
468  mPath.moveTo( 0, 0 );
469  mPath.lineTo( -1, 1 );
470  return true;
471  }
472 
473  return false;
474 }
475 
477 {
478  QPainter *p = context.renderContext().painter();
479  if ( !p )
480  {
481  return;
482  }
483 
484  QgsExpression *sizeExpression = expression( "size" );
485  bool hasDataDefinedSize = context.renderHints() & QgsSymbolV2::DataDefinedSizeScale || sizeExpression;
486 
487  double scaledSize = mSize;
488  if ( hasDataDefinedSize )
489  {
490  if ( sizeExpression )
491  {
492  scaledSize = sizeExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble();
493  }
494 
496  {
497  scaledSize = sqrt( scaledSize );
498  }
499  }
500 
501  //offset
502  double offsetX = 0;
503  double offsetY = 0;
504  markerOffset( context, scaledSize, scaledSize, offsetX, offsetY );
505  QPointF off( offsetX, offsetY );
506 
507  //angle
508  double angle = mAngle;
509  if ( mAngleExpression )
510  {
511  angle = mAngleExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble();
512  }
513  if ( angle )
514  off = _rotatedOffset( off, angle );
515 
516  //data defined shape?
517  if ( mNameExpression )
518  {
519  QString name = mNameExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString();
520  if ( !prepareShape( name ) ) // drawing as a polygon
521  {
522  preparePath( name ); // drawing as a painter path
523  }
524  }
525 
526  if ( mUsingCache )
527  {
528  // we will use cached image
529  QImage &img = context.selected() ? mSelCache : mCache;
530  double s = img.width() / context.renderContext().rasterScaleFactor();
531  p->drawImage( QRectF( point.x() - s / 2.0 + off.x(),
532  point.y() - s / 2.0 + off.y(),
533  s, s ), img );
534  }
535  else
536  {
537  QMatrix transform;
538 
539  // move to the desired position
540  transform.translate( point.x() + off.x(), point.y() + off.y() );
541 
542  // resize if necessary
543  if ( hasDataDefinedSize )
544  {
545 
547 
548  double half = s / 2.0;
549  transform.scale( half, half );
550  }
551 
552  bool hasDataDefinedRotation = context.renderHints() & QgsSymbolV2::DataDefinedRotation || mAngleExpression;
553  if ( angle != 0 && hasDataDefinedRotation )
554  transform.rotate( angle );
555 
556  QgsExpression* colorExpression = expression( "color" );
557  QgsExpression* colorBorderExpression = expression( "color_border" );
558  QgsExpression* outlineWidthExpression = expression( "outline_width" );
559  if ( colorExpression )
560  {
561  mBrush.setColor( QgsSymbolLayerV2Utils::decodeColor( colorExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() ) );
562  }
563  if ( colorBorderExpression )
564  {
565  mPen.setColor( QgsSymbolLayerV2Utils::decodeColor( colorBorderExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() ) );
566  mSelPen.setColor( QgsSymbolLayerV2Utils::decodeColor( colorBorderExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() ) );
567  }
568  if ( outlineWidthExpression )
569  {
570  double outlineWidth = outlineWidthExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble();
573  }
574 
575  p->setBrush( context.selected() ? mSelBrush : mBrush );
576  p->setPen( context.selected() ? mSelPen : mPen );
577 
578  if ( !mPolygon.isEmpty() )
579  p->drawPolygon( transform.map( mPolygon ) );
580  else
581  p->drawPath( transform.map( mPath ) );
582  }
583 }
584 
585 
587 {
588  QgsStringMap map;
589  map["name"] = mName;
590  map["color"] = QgsSymbolLayerV2Utils::encodeColor( mColor );
591  map["color_border"] = QgsSymbolLayerV2Utils::encodeColor( mBorderColor );
592  map["size"] = QString::number( mSize );
594  map["size_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mSizeMapUnitScale );
595  map["angle"] = QString::number( mAngle );
596  map["offset"] = QgsSymbolLayerV2Utils::encodePoint( mOffset );
598  map["offset_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOffsetMapUnitScale );
600  map["outline_style"] = QgsSymbolLayerV2Utils::encodePenStyle( mOutlineStyle );
601  map["outline_width"] = QString::number( mOutlineWidth );
602  map["outline_width_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mOutlineWidthUnit );
603  map["outline_width_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOutlineWidthMapUnitScale );
604  map["horizontal_anchor_point"] = QString::number( mHorizontalAnchorPoint );
605  map["vertical_anchor_point"] = QString::number( mVerticalAnchorPoint );
606 
607 
608  //data define properties
610  return map;
611 }
612 
614 {
616  m->setOffset( mOffset );
617  m->setSizeUnit( mSizeUnit );
628  return m;
629 }
630 
631 void QgsSimpleMarkerSymbolLayerV2::writeSldMarker( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const
632 {
633  // <Graphic>
634  QDomElement graphicElem = doc.createElement( "se:Graphic" );
635  element.appendChild( graphicElem );
636 
638 
639  // <Rotation>
640  QString angleFunc;
641  bool ok;
642  double angle = props.value( "angle", "0" ).toDouble( &ok );
643  if ( !ok )
644  {
645  angleFunc = QString( "%1 + %2" ).arg( props.value( "angle", "0" ) ).arg( mAngle );
646  }
647  else if ( angle + mAngle != 0 )
648  {
649  angleFunc = QString::number( angle + mAngle );
650  }
651  QgsSymbolLayerV2Utils::createRotationElement( doc, graphicElem, angleFunc );
652 
653  // <Displacement>
655 }
656 
657 QString QgsSimpleMarkerSymbolLayerV2::ogrFeatureStyle( double mmScaleFactor, double mapUnitScaleFactor ) const
658 {
659  Q_UNUSED( mmScaleFactor );
660  Q_UNUSED( mapUnitScaleFactor );
661 #if 0
662  QString ogrType = "3"; //default is circle
663  if ( mName == "square" )
664  {
665  ogrType = "5";
666  }
667  else if ( mName == "triangle" )
668  {
669  ogrType = "7";
670  }
671  else if ( mName == "star" )
672  {
673  ogrType = "9";
674  }
675  else if ( mName == "circle" )
676  {
677  ogrType = "3";
678  }
679  else if ( mName == "cross" )
680  {
681  ogrType = "0";
682  }
683  else if ( mName == "x" || mName == "cross2" )
684  {
685  ogrType = "1";
686  }
687  else if ( mName == "line" )
688  {
689  ogrType = "10";
690  }
691 
692  QString ogrString;
693  ogrString.append( "SYMBOL(" );
694  ogrString.append( "id:" );
695  ogrString.append( "\"" );
696  ogrString.append( "ogr-sym-" );
697  ogrString.append( ogrType );
698  ogrString.append( "\"" );
699  ogrString.append( ",c:" );
700  ogrString.append( mColor.name() );
701  ogrString.append( ",o:" );
702  ogrString.append( mBorderColor.name() );
703  ogrString.append( QString( ",s:%1mm" ).arg( mSize ) );
704  ogrString.append( ")" );
705  return ogrString;
706 #endif //0
707 
708  QString ogrString;
709  ogrString.append( "PEN(" );
710  ogrString.append( "c:" );
711  ogrString.append( mColor.name() );
712  ogrString.append( ",w:" );
713  ogrString.append( QString::number( mSize ) );
714  ogrString.append( "mm" );
715  ogrString.append( ")" );
716  return ogrString;
717 }
718 
720 {
721  QgsDebugMsg( "Entered." );
722 
723  QDomElement graphicElem = element.firstChildElement( "Graphic" );
724  if ( graphicElem.isNull() )
725  return NULL;
726 
727  QString name = "square";
728  QColor color, borderColor;
729  double borderWidth, size;
730  Qt::PenStyle borderStyle;
731 
732  if ( !QgsSymbolLayerV2Utils::wellKnownMarkerFromSld( graphicElem, name, color, borderColor, borderStyle, borderWidth, size ) )
733  return NULL;
734 
735  double angle = 0.0;
736  QString angleFunc;
737  if ( QgsSymbolLayerV2Utils::rotationFromSldElement( graphicElem, angleFunc ) )
738  {
739  bool ok;
740  double d = angleFunc.toDouble( &ok );
741  if ( ok )
742  angle = d;
743  }
744 
745  QPointF offset;
747 
748  QgsSimpleMarkerSymbolLayerV2 *m = new QgsSimpleMarkerSymbolLayerV2( name, color, borderColor, size );
749  m->setAngle( angle );
750  m->setOffset( offset );
751  m->setOutlineStyle( borderStyle );
752  return m;
753 }
754 
756 {
757  Q_UNUSED( context );
758 
759  if ( mPolygon.count() != 0 )
760  {
761  p->drawPolygon( mPolygon );
762  }
763  else
764  {
765  p->drawPath( mPath );
766  }
767 }
768 
769 bool QgsSimpleMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, const QPointF& shift ) const
770 {
771  //data defined size?
772  double size = mSize;
773 
774  QgsExpression *sizeExpression = expression( "size" );
775  bool hasDataDefinedSize = false;
776  if ( context )
777  {
778  hasDataDefinedSize = context->renderHints() & QgsSymbolV2::DataDefinedSizeScale || sizeExpression;
779  }
780 
781  //data defined size
782  if ( hasDataDefinedSize )
783  {
784  if ( sizeExpression )
785  {
786  size = sizeExpression->evaluate( const_cast<QgsFeature*>( context->feature() ) ).toDouble();
787  }
788 
789  switch ( mScaleMethod )
790  {
792  size = sqrt( size );
793  break;
795  break;
796  }
797 
799  }
800  if ( mSizeUnit == QgsSymbolV2::MM )
801  {
802  size *= mmMapUnitScaleFactor;
803  }
804  double halfSize = size / 2.0;
805 
806  //outlineWidth
807  double outlineWidth = mOutlineWidth;
808  QgsExpression* outlineWidthExpression = expression( "outline_width" );
809  if ( outlineWidthExpression )
810  {
811  outlineWidth = outlineWidthExpression->evaluate( const_cast<QgsFeature*>( context->feature() ) ).toDouble();
812  }
813  if ( mSizeUnit == QgsSymbolV2::MM )
814  {
815  outlineWidth *= mmMapUnitScaleFactor;
816  }
817 
818  //color
819  QColor c = mPen.color();
820  if ( mPen.style() == Qt::NoPen )
821  {
822  c = mBrush.color();
823  }
824  QgsExpression* colorExpression = expression( "color" );
825  if ( colorExpression )
826  {
827  c = QgsSymbolLayerV2Utils::decodeColor( colorExpression->evaluate( *f ).toString() );
828  }
829  int colorIndex = QgsDxfExport::closestColorMatch( c.rgb() );
830 
831  //offset
832  double offsetX = 0;
833  double offsetY = 0;
834  markerOffset( *context, offsetX, offsetY );
835  QPointF off( offsetX, offsetY );
836 
837  //angle
838  double angle = mAngle;
839  QgsExpression* angleExpression = expression( "angle" );
840  if ( angleExpression )
841  {
842  angle = angleExpression->evaluate( const_cast<QgsFeature*>( context->feature() ) ).toDouble();
843  }
844  angle = -angle; //rotation in Qt is counterclockwise
845  if ( angle )
846  off = _rotatedOffset( off, angle );
847 
848  if ( mSizeUnit == QgsSymbolV2::MM )
849  {
850  off *= mmMapUnitScaleFactor;
851  }
852 
853  QTransform t;
854  t.translate( shift.x() + offsetX, shift.y() + offsetY );
855 
856  if ( angle != 0 )
857  t.rotate( angle );
858 
859  //data defined symbol name
860 
861  if ( mName == "circle" )
862  {
863  e.writeGroup( 0, "CIRCLE" );
864  e.writeGroup( 8, layerName );
865 
866  e.writeGroup( 62, colorIndex );
867  e.writeGroup( 10, shift.x() );
868  e.writeGroup( 20, shift.y() );
869  e.writeGroup( 30, 0.0 );
870  e.writeGroup( 40, halfSize );
871  }
872  else if ( mName == "square" || mName == "rectangle" )
873  {
874  QPointF pt1 = t.map( QPointF( -halfSize, -halfSize ) );
875  QPointF pt2 = t.map( QPointF( halfSize, -halfSize ) );
876  QPointF pt3 = t.map( QPointF( -halfSize, halfSize ) );
877  QPointF pt4 = t.map( QPointF( halfSize, halfSize ) );
878  e.writeSolid( layerName, colorIndex, QgsPoint( pt1.x(), pt1.y() ), QgsPoint( pt2.x(), pt2.y() ), QgsPoint( pt3.x(), pt3.y() ), QgsPoint( pt4.x(), pt4.y() ) );
879  }
880  else if ( mName == "diamond" )
881  {
882  QPointF pt1 = t.map( QPointF( -halfSize, 0 ) );
883  QPointF pt2 = t.map( QPointF( 0, -halfSize ) );
884  QPointF pt3 = t.map( QPointF( 0, halfSize ) );
885  QPointF pt4 = t.map( QPointF( halfSize, 0 ) );
886  e.writeSolid( layerName, colorIndex, QgsPoint( pt1.x(), pt1.y() ), QgsPoint( pt2.x(), pt2.y() ), QgsPoint( pt3.x(), pt3.y() ), QgsPoint( pt4.x(), pt4.y() ) );
887  }
888  else if ( mName == "triangle" )
889  {
890  QPointF pt1 = t.map( QPointF( -halfSize, -halfSize ) );
891  QPointF pt2 = t.map( QPointF( halfSize, -halfSize ) );
892  QPointF pt3 = t.map( QPointF( 0, halfSize ) );
893  e.writeSolid( layerName, colorIndex, QgsPoint( pt1.x(), pt1.y() ), QgsPoint( pt2.x(), pt2.y() ), QgsPoint( pt3.x(), pt3.y() ), QgsPoint( pt3.x(), pt3.y() ) );
894  }
895  /*else if( mName == "equilateral_triangle" )
896  {
897 
898  }*/
899  else if ( mName == "line" )
900  {
901  QPointF pt1 = t.map( QPointF( 0, halfSize ) );
902  QPointF pt2 = t.map( QPointF( 0, -halfSize ) );
903  e.writeLine( QgsPoint( pt1.x(), pt1.y() ), QgsPoint( pt2.x(), pt2.y() ), layerName, "CONTINUOUS", colorIndex, outlineWidth );
904  }
905  else if ( mName == "coss" )
906  {
907  QPointF pt1 = t.map( QPointF( -halfSize, 0 ) );
908  QPointF pt2 = t.map( QPointF( halfSize, 0 ) );
909  QPointF pt3 = t.map( QPointF( 0, -halfSize ) );
910  QPointF pt4 = t.map( QPointF( 0, halfSize ) );
911  e.writeLine( QgsPoint( pt1.x(), pt1.y() ), QgsPoint( pt2.x(), pt2.y() ), layerName, "CONTINUOUS", colorIndex, outlineWidth );
912  e.writeLine( QgsPoint( pt3.x(), pt3.y() ), QgsPoint( pt4.x(), pt4.y() ), layerName, "CONTINUOUS", colorIndex, outlineWidth );
913  }
914  else if ( mName == "x" || mName == "cross2" )
915  {
916  QPointF pt1 = t.map( QPointF( -halfSize, -halfSize ) );
917  QPointF pt2 = t.map( QPointF( halfSize, halfSize ) );
918  QPointF pt3 = t.map( QPointF( -halfSize, halfSize ) );
919  QPointF pt4 = t.map( QPointF( halfSize, -halfSize ) );
920  e.writeLine( QgsPoint( pt1.x(), pt1.y() ), QgsPoint( pt2.x(), pt2.y() ), layerName, "CONTINUOUS", colorIndex, outlineWidth );
921  e.writeLine( QgsPoint( pt3.x(), pt3.y() ), QgsPoint( pt4.x(), pt4.y() ), layerName, "CONTINUOUS", colorIndex, outlineWidth );
922  }
923  else if ( mName == "arrowhead" )
924  {
925  QPointF pt1 = t.map( QPointF( -halfSize, halfSize ) );
926  QPointF pt2 = t.map( QPointF( 0, 0 ) );
927  QPointF pt3 = t.map( QPointF( -halfSize, -halfSize ) );
928  e.writeLine( QgsPoint( pt1.x(), pt1.y() ), QgsPoint( pt2.x(), pt2.y() ), layerName, "CONTINUOUS", colorIndex, outlineWidth );
929  e.writeLine( QgsPoint( pt3.x(), pt3.y() ), QgsPoint( pt2.x(), pt2.y() ), layerName, "CONTINUOUS", colorIndex, outlineWidth );
930  }
931  else if ( mName == "filled_arrowhead" )
932  {
933  QPointF pt1 = t.map( QPointF( -halfSize, halfSize ) );
934  QPointF pt2 = t.map( QPointF( 0, 0 ) );
935  QPointF pt3 = t.map( QPointF( -halfSize, -halfSize ) );
936  e.writeSolid( layerName, colorIndex, QgsPoint( pt1.x(), pt1.y() ), QgsPoint( pt2.x(), pt2.y() ), QgsPoint( pt3.x(), pt3.y() ), QgsPoint( pt3.x(), pt3.y() ) );
937  }
938  else
939  {
940  return false;
941  }
942  return true;
943 }
944 
945 
947 {
949  mOutlineWidthUnit = unit;
950 }
951 
953 {
955  {
956  return mOutlineWidthUnit;
957  }
958  return QgsSymbolV2::Mixed;
959 }
960 
962 {
965 }
966 
968 {
970  {
972  }
973  return QgsMapUnitScale();
974 }
975 
977 
978 
980 {
982  mSize = size;
983  mAngle = angle;
984  mOffset = QPointF( 0, 0 );
986  mOutlineWidth = 1.0;
988  mFillColor = QColor( Qt::black );
989  mOutlineColor = QColor( Qt::black );
990 }
991 
992 
994 {
995  QString name = DEFAULT_SVGMARKER_NAME;
996  double size = DEFAULT_SVGMARKER_SIZE;
999 
1000  if ( props.contains( "name" ) )
1001  name = props["name"];
1002  if ( props.contains( "size" ) )
1003  size = props["size"].toDouble();
1004  if ( props.contains( "angle" ) )
1005  angle = props["angle"].toDouble();
1006  if ( props.contains( "scale_method" ) )
1007  scaleMethod = QgsSymbolLayerV2Utils::decodeScaleMethod( props["scale_method"] );
1008 
1009  QgsSvgMarkerSymbolLayerV2* m = new QgsSvgMarkerSymbolLayerV2( name, size, angle, scaleMethod );
1010 
1011  //we only check the svg default parameters if necessary, since it could be expensive
1012  if ( !props.contains( "fill" ) && !props.contains( "outline" ) && !props.contains( "outline-width" ) )
1013  {
1014  QColor fillColor, outlineColor;
1015  double outlineWidth;
1016  bool hasFillParam, hasOutlineParam, hasOutlineWidthParam;
1017  QgsSvgCache::instance()->containsParams( name, hasFillParam, fillColor, hasOutlineParam, outlineColor, hasOutlineWidthParam, outlineWidth );
1018  if ( hasFillParam )
1019  {
1020  m->setFillColor( fillColor );
1021  }
1022  if ( hasOutlineParam )
1023  {
1024  m->setOutlineColor( outlineColor );
1025  }
1026  if ( hasOutlineWidthParam )
1027  {
1028  m->setOutlineWidth( outlineWidth );
1029  }
1030  }
1031 
1032  if ( props.contains( "size_unit" ) )
1033  m->setSizeUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["size_unit"] ) );
1034  if ( props.contains( "size_map_unit_scale" ) )
1035  m->setSizeMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( props["size_map_unit_scale"] ) );
1036  if ( props.contains( "offset" ) )
1037  m->setOffset( QgsSymbolLayerV2Utils::decodePoint( props["offset"] ) );
1038  if ( props.contains( "offset_unit" ) )
1039  m->setOffsetUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["offset_unit"] ) );
1040  if ( props.contains( "offset_map_unit_scale" ) )
1041  m->setOffsetMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( props["offset_map_unit_scale"] ) );
1042  if ( props.contains( "fill" ) )
1043  m->setFillColor( QColor( props["fill"] ) );
1044  if ( props.contains( "outline" ) )
1045  m->setOutlineColor( QColor( props["outline"] ) );
1046  if ( props.contains( "outline-width" ) )
1047  m->setOutlineWidth( props["outline-width"].toDouble() );
1048  if ( props.contains( "outline_width_unit" ) )
1049  m->setOutlineWidthUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["outline_width_unit"] ) );
1050  if ( props.contains( "outline_width_map_unit_scale" ) )
1051  m->setOutlineWidthMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( props["outline_width_map_unit_scale"] ) );
1052 
1053  if ( props.contains( "horizontal_anchor_point" ) )
1054  {
1055  m->setHorizontalAnchorPoint( QgsMarkerSymbolLayerV2::HorizontalAnchorPoint( props[ "horizontal_anchor_point" ].toInt() ) );
1056  }
1057  if ( props.contains( "vertical_anchor_point" ) )
1058  {
1059  m->setVerticalAnchorPoint( QgsMarkerSymbolLayerV2::VerticalAnchorPoint( props[ "vertical_anchor_point" ].toInt() ) );
1060  }
1061 
1062  //data defined properties
1063  if ( props.contains( "size_expression" ) )
1064  {
1065  m->setDataDefinedProperty( "size", props["size_expression"] );
1066  }
1067  if ( props.contains( "outline-width_expression" ) )
1068  {
1069  m->setDataDefinedProperty( "outline-width", props["outline-width_expression"] );
1070  }
1071  if ( props.contains( "angle_expression" ) )
1072  {
1073  m->setDataDefinedProperty( "angle", props["angle_expression"] );
1074  }
1075  if ( props.contains( "offset_expression" ) )
1076  {
1077  m->setDataDefinedProperty( "offset", props["offset_expression"] );
1078  }
1079  if ( props.contains( "name_expression" ) )
1080  {
1081  m->setDataDefinedProperty( "name", props["name_expression"] );
1082  }
1083  if ( props.contains( "fill_expression" ) )
1084  {
1085  m->setDataDefinedProperty( "fill", props["fill_expression"] );
1086  }
1087  if ( props.contains( "outline_expression" ) )
1088  {
1089  m->setDataDefinedProperty( "outline", props["outline_expression"] );
1090  }
1091  if ( props.contains( "horizontal_anchor_point_expression" ) )
1092  {
1093  m->setDataDefinedProperty( "horizontal_anchor_point", props[ "horizontal_anchor_point_expression" ] );
1094  }
1095  if ( props.contains( "vertical_anchor_point_expression" ) )
1096  {
1097  m->setDataDefinedProperty( "vertical_anchor_point", props[ "vertical_anchor_point_expression" ] );
1098  }
1099  return m;
1100 }
1101 
1103 {
1104  mPath = path;
1105  QColor fillColor, outlineColor;
1106  double outlineWidth;
1107  bool hasFillParam, hasOutlineParam, hasOutlineWidthParam;
1108  QgsSvgCache::instance()->containsParams( path, hasFillParam, fillColor, hasOutlineParam, outlineColor, hasOutlineWidthParam, outlineWidth );
1109  if ( hasFillParam )
1110  {
1111  setFillColor( fillColor );
1112  }
1113  if ( hasOutlineParam )
1114  {
1115  setOutlineColor( outlineColor );
1116  }
1117  if ( hasOutlineWidthParam )
1118  {
1119  setOutlineWidth( outlineWidth );
1120  }
1121 }
1122 
1123 
1125 {
1126  return "SvgMarker";
1127 }
1128 
1130 {
1131  QgsMarkerSymbolLayerV2::startRender( context ); // get anchor point expressions
1132  mOrigSize = mSize; // save in case the size would be data defined
1133  Q_UNUSED( context );
1134  prepareExpressions( context.fields(), context.renderContext().rendererScale() );
1135 }
1136 
1138 {
1139  Q_UNUSED( context );
1140 }
1141 
1143 {
1144  QPainter *p = context.renderContext().painter();
1145  if ( !p )
1146  return;
1147 
1148  double scaledSize = mSize;
1149  QgsExpression* sizeExpression = expression( "size" );
1150 
1151  bool hasDataDefinedSize = context.renderHints() & QgsSymbolV2::DataDefinedSizeScale || sizeExpression;
1152 
1153  if ( sizeExpression )
1154  {
1155  scaledSize = sizeExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble();
1156  }
1157 
1158  if ( hasDataDefinedSize )
1159  {
1160  switch ( mScaleMethod )
1161  {
1163  scaledSize = sqrt( scaledSize );
1164  break;
1166  break;
1167  }
1168  }
1169 
1171 
1172  //don't render symbols with size below one or above 10,000 pixels
1173  if (( int )size < 1 || 10000.0 < size )
1174  {
1175  return;
1176  }
1177 
1178  p->save();
1179 
1180  //offset
1181  double offsetX = 0;
1182  double offsetY = 0;
1183  markerOffset( context, scaledSize, scaledSize, offsetX, offsetY );
1184  QPointF outputOffset( offsetX, offsetY );
1185 
1186  double angle = mAngle;
1187  QgsExpression* angleExpression = expression( "angle" );
1188  if ( angleExpression )
1189  {
1190  angle = angleExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble();
1191  }
1192  if ( angle )
1193  outputOffset = _rotatedOffset( outputOffset, angle );
1194  p->translate( point + outputOffset );
1195 
1196  bool rotated = !qgsDoubleNear( angle, 0 );
1197  bool drawOnScreen = qgsDoubleNear( context.renderContext().rasterScaleFactor(), 1.0, 0.1 );
1198  if ( rotated )
1199  p->rotate( angle );
1200 
1201  QString path = mPath;
1202  QgsExpression* nameExpression = expression( "name" );
1203  if ( nameExpression )
1204  {
1205  path = nameExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString();
1206  }
1207 
1208  double outlineWidth = mOutlineWidth;
1209  QgsExpression* outlineWidthExpression = expression( "outline_width" );
1210  if ( outlineWidthExpression )
1211  {
1212  outlineWidth = outlineWidthExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble();
1213  }
1214 
1215  QColor fillColor = mFillColor;
1216  QgsExpression* fillExpression = expression( "fill" );
1217  if ( fillExpression )
1218  {
1219  fillColor = QgsSymbolLayerV2Utils::decodeColor( fillExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() );
1220  }
1221 
1222  QColor outlineColor = mOutlineColor;
1223  QgsExpression* outlineExpression = expression( "outline" );
1224  if ( outlineExpression )
1225  {
1226  outlineColor = QgsSymbolLayerV2Utils::decodeColor( outlineExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toString() );
1227  }
1228 
1229 
1230  bool fitsInCache = true;
1231  bool usePict = true;
1232  double hwRatio = 1.0;
1233  if ( drawOnScreen && !rotated )
1234  {
1235  usePict = false;
1236  const QImage& img = QgsSvgCache::instance()->svgAsImage( path, size, fillColor, outlineColor, outlineWidth,
1237  context.renderContext().scaleFactor(), context.renderContext().rasterScaleFactor(), fitsInCache );
1238  if ( fitsInCache && img.width() > 1 )
1239  {
1240  //consider transparency
1241  if ( !qgsDoubleNear( context.alpha(), 1.0 ) )
1242  {
1243  QImage transparentImage = img.copy();
1244  QgsSymbolLayerV2Utils::multiplyImageOpacity( &transparentImage, context.alpha() );
1245  p->drawImage( -transparentImage.width() / 2.0, -transparentImage.height() / 2.0, transparentImage );
1246  hwRatio = ( double )transparentImage.height() / ( double )transparentImage.width();
1247  }
1248  else
1249  {
1250  p->drawImage( -img.width() / 2.0, -img.height() / 2.0, img );
1251  hwRatio = ( double )img.height() / ( double )img.width();
1252  }
1253  }
1254  }
1255 
1256  if ( usePict || !fitsInCache )
1257  {
1258  p->setOpacity( context.alpha() );
1259  const QPicture& pct = QgsSvgCache::instance()->svgAsPicture( path, size, fillColor, outlineColor, outlineWidth,
1261 
1262  if ( pct.width() > 1 )
1263  {
1264  p->save();
1265  _fixQPictureDPI( p );
1266  p->drawPicture( 0, 0, pct );
1267  p->restore();
1268  hwRatio = ( double )pct.height() / ( double )pct.width();
1269  }
1270  }
1271 
1272  if ( context.selected() )
1273  {
1274  QPen pen( context.renderContext().selectionColor() );
1276  if ( penWidth > size / 20 )
1277  {
1278  // keep the pen width from covering symbol
1279  penWidth = size / 20;
1280  }
1281  double penOffset = penWidth / 2;
1282  pen.setWidth( penWidth );
1283  p->setPen( pen );
1284  p->setBrush( Qt::NoBrush );
1285  double wSize = size + penOffset;
1286  double hSize = size * hwRatio + penOffset;
1287  p->drawRect( QRectF( -wSize / 2.0, -hSize / 2.0, wSize, hSize ) );
1288  }
1289 
1290  p->restore();
1291 }
1292 
1293 
1295 {
1296  QgsStringMap map;
1298  map["size"] = QString::number( mSize );
1299  map["size_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mSizeUnit );
1300  map["size_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mSizeMapUnitScale );
1301  map["angle"] = QString::number( mAngle );
1302  map["offset"] = QgsSymbolLayerV2Utils::encodePoint( mOffset );
1303  map["offset_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mOffsetUnit );
1304  map["offset_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOffsetMapUnitScale );
1305  map["scale_method"] = QgsSymbolLayerV2Utils::encodeScaleMethod( mScaleMethod );
1306  map["fill"] = mFillColor.name();
1307  map["outline"] = mOutlineColor.name();
1308  map["outline-width"] = QString::number( mOutlineWidth );
1309  map["outline_width_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mOutlineWidthUnit );
1310  map["outline_width_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOutlineWidthMapUnitScale );
1311  map["horizontal_anchor_point"] = QString::number( mHorizontalAnchorPoint );
1312  map["vertical_anchor_point"] = QString::number( mVerticalAnchorPoint );
1313 
1315  return map;
1316 }
1317 
1319 {
1321  m->setFillColor( mFillColor );
1326  m->setOffset( mOffset );
1327  m->setOffsetUnit( mOffsetUnit );
1329  m->setSizeUnit( mSizeUnit );
1334  return m;
1335 }
1336 
1338 {
1340  mOutlineWidthUnit = unit;
1341 }
1342 
1344 {
1346  if ( unit != mOutlineWidthUnit )
1347  {
1348  return QgsSymbolV2::Mixed;
1349  }
1350  return unit;
1351 }
1352 
1354 {
1356  mOutlineWidthMapUnitScale = scale;
1357 }
1358 
1360 {
1362  {
1364  }
1365  return QgsMapUnitScale();
1366 }
1367 
1368 void QgsSvgMarkerSymbolLayerV2::writeSldMarker( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const
1369 {
1370  // <Graphic>
1371  QDomElement graphicElem = doc.createElement( "se:Graphic" );
1372  element.appendChild( graphicElem );
1373 
1374  QgsSymbolLayerV2Utils::externalGraphicToSld( doc, graphicElem, mPath, "image/svg+xml", mFillColor, mSize );
1375 
1376  // <Rotation>
1377  QString angleFunc;
1378  bool ok;
1379  double angle = props.value( "angle", "0" ).toDouble( &ok );
1380  if ( !ok )
1381  {
1382  angleFunc = QString( "%1 + %2" ).arg( props.value( "angle", "0" ) ).arg( mAngle );
1383  }
1384  else if ( angle + mAngle != 0 )
1385  {
1386  angleFunc = QString::number( angle + mAngle );
1387  }
1388 
1389  QgsSymbolLayerV2Utils::createRotationElement( doc, graphicElem, angleFunc );
1390 
1391  // <Displacement>
1393 }
1394 
1396 {
1397  QgsDebugMsg( "Entered." );
1398 
1399  QDomElement graphicElem = element.firstChildElement( "Graphic" );
1400  if ( graphicElem.isNull() )
1401  return NULL;
1402 
1403  QString path, mimeType;
1404  QColor fillColor;
1405  double size;
1406 
1407  if ( !QgsSymbolLayerV2Utils::externalGraphicFromSld( graphicElem, path, mimeType, fillColor, size ) )
1408  return NULL;
1409 
1410  if ( mimeType != "image/svg+xml" )
1411  return NULL;
1412 
1413  double angle = 0.0;
1414  QString angleFunc;
1415  if ( QgsSymbolLayerV2Utils::rotationFromSldElement( graphicElem, angleFunc ) )
1416  {
1417  bool ok;
1418  double d = angleFunc.toDouble( &ok );
1419  if ( ok )
1420  angle = d;
1421  }
1422 
1423  QPointF offset;
1425 
1427  m->setFillColor( fillColor );
1428  //m->setOutlineColor( outlineColor );
1429  //m->setOutlineWidth( outlineWidth );
1430  m->setAngle( angle );
1431  m->setOffset( offset );
1432  return m;
1433 }
1434 
1435 bool QgsSvgMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f,
1436  const QPointF& shift ) const
1437 {
1438  Q_UNUSED( layerName );
1439  Q_UNUSED( shift ); //todo...
1440 
1441  QSvgRenderer r( mPath );
1442  if ( !r.isValid() )
1443  {
1444  return false;
1445  }
1446 
1447  QgsDxfPaintDevice pd( &e );
1448  pd.setDrawingSize( QSizeF( r.defaultSize() ) );
1449 
1450  //size
1451  double size = mSize;
1452  QgsExpression* sizeExpression = expression( "size" );
1453  bool hasDataDefinedSize = context->renderHints() & QgsSymbolV2::DataDefinedSizeScale || sizeExpression;
1454 
1455  if ( sizeExpression )
1456  {
1457  size = sizeExpression->evaluate( *f ).toDouble();
1458  }
1459 
1460  if ( hasDataDefinedSize )
1461  {
1462  switch ( mScaleMethod )
1463  {
1465  size = sqrt( size );
1466  break;
1468  break;
1469  }
1470  }
1471 
1472  if ( mSizeUnit == QgsSymbolV2::MM )
1473  {
1474  size *= mmMapUnitScaleFactor;
1475  }
1476 
1477  double halfSize = size / 2.0;
1478 
1479  //offset, angle
1480  QPointF offset = mOffset;
1481  QgsExpression* offsetExpression = expression( "offset" );
1482  if ( offsetExpression )
1483  {
1484  QString offsetString = offsetExpression->evaluate( *f ).toString();
1485  offset = QgsSymbolLayerV2Utils::decodePoint( offsetString );
1486  }
1487  double offsetX = offset.x();
1488  double offsetY = offset.y();
1489  if ( mSizeUnit == QgsSymbolV2::MM )
1490  {
1491  offsetX *= mmMapUnitScaleFactor;
1492  offsetY *= mmMapUnitScaleFactor;
1493  }
1494 
1495  QPointF outputOffset( offsetX, offsetY );
1496 
1497  double angle = mAngle;
1498  QgsExpression* angleExpression = expression( "angle" );
1499  if ( angleExpression )
1500  {
1501  angle = angleExpression->evaluate( *f ).toDouble();
1502  }
1503  //angle = -angle; //rotation in Qt is counterclockwise
1504  if ( angle )
1505  outputOffset = _rotatedOffset( outputOffset, angle );
1506 
1507  QPainter p;
1508  p.begin( &pd );
1509  if ( !qgsDoubleNear( angle, 0.0 ) )
1510  {
1511  p.translate( r.defaultSize().width() / 2.0, r.defaultSize().height() / 2.0 );
1512  p.rotate( angle );
1513  p.translate( -r.defaultSize().width() / 2.0, -r.defaultSize().height() / 2.0 );
1514  }
1515  pd.setShift( shift );
1516  pd.setOutputSize( QRectF( -halfSize, -halfSize, size, size ) );
1517  pd.setLayer( layerName );
1518  r.render( &p );
1519  p.end();
1520  return true;
1521 }
1522 
1524 
1525 QgsFontMarkerSymbolLayerV2::QgsFontMarkerSymbolLayerV2( QString fontFamily, QChar chr, double pointSize, QColor color, double angle )
1526 {
1528  mChr = chr;
1529  mColor = color;
1530  mAngle = angle;
1531  mSize = pointSize;
1533  mOffset = QPointF( 0, 0 );
1535 }
1536 
1538 {
1540  QChar chr = DEFAULT_FONTMARKER_CHR;
1541  double pointSize = DEFAULT_FONTMARKER_SIZE;
1544 
1545  if ( props.contains( "font" ) )
1546  fontFamily = props["font"];
1547  if ( props.contains( "chr" ) && props["chr"].length() > 0 )
1548  chr = props["chr"].at( 0 );
1549  if ( props.contains( "size" ) )
1550  pointSize = props["size"].toDouble();
1551  if ( props.contains( "color" ) )
1552  color = QgsSymbolLayerV2Utils::decodeColor( props["color"] );
1553  if ( props.contains( "angle" ) )
1554  angle = props["angle"].toDouble();
1555 
1556  QgsFontMarkerSymbolLayerV2* m = new QgsFontMarkerSymbolLayerV2( fontFamily, chr, pointSize, color, angle );
1557  if ( props.contains( "offset" ) )
1558  m->setOffset( QgsSymbolLayerV2Utils::decodePoint( props["offset"] ) );
1559  if ( props.contains( "offset_unit" ) )
1560  m->setOffsetUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["offset_unit" ] ) );
1561  if ( props.contains( "offset_map_unit_scale" ) )
1562  m->setOffsetMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( props["offset_map_unit_scale" ] ) );
1563  if ( props.contains( "size_unit" ) )
1564  m->setSizeUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["size_unit"] ) );
1565  if ( props.contains( "size_map_unit_scale" ) )
1566  m->setSizeMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( props["size_map_unit_scale"] ) );
1567  if ( props.contains( "horizontal_anchor_point" ) )
1568  {
1569  m->setHorizontalAnchorPoint( QgsMarkerSymbolLayerV2::HorizontalAnchorPoint( props[ "horizontal_anchor_point" ].toInt() ) );
1570  }
1571  if ( props.contains( "vertical_anchor_point" ) )
1572  {
1573  m->setVerticalAnchorPoint( QgsMarkerSymbolLayerV2::VerticalAnchorPoint( props[ "vertical_anchor_point" ].toInt() ) );
1574  }
1575  return m;
1576 }
1577 
1579 {
1580  return "FontMarker";
1581 }
1582 
1584 {
1585  mFont = QFont( mFontFamily );
1587  QFontMetrics fm( mFont );
1588  mChrOffset = QPointF( fm.width( mChr ) / 2, -fm.ascent() / 2 );
1589 
1590  mOrigSize = mSize; // save in case the size would be data defined
1591 }
1592 
1594 {
1595  Q_UNUSED( context );
1596 }
1597 
1599 {
1600  QPainter *p = context.renderContext().painter();
1601  if ( !p )
1602  return;
1603 
1604  QColor penColor = context.selected() ? context.renderContext().selectionColor() : mColor;
1605  penColor.setAlphaF( mColor.alphaF() * context.alpha() );
1606  p->setPen( penColor );
1607  p->setFont( mFont );
1608 
1609  p->save();
1610  //offset
1611  double offsetX = 0;
1612  double offsetY = 0;
1613  markerOffset( context, offsetX, offsetY );
1614  QPointF outputOffset( offsetX, offsetY );
1615  if ( mAngle )
1616  outputOffset = _rotatedOffset( outputOffset, mAngle );
1617  p->translate( point + outputOffset );
1618 
1620  {
1621  double s = mSize / mOrigSize;
1622  p->scale( s, s );
1623  }
1624 
1625  if ( mAngle != 0 )
1626  p->rotate( mAngle );
1627 
1628  p->drawText( -mChrOffset, mChr );
1629  p->restore();
1630 }
1631 
1633 {
1634  QgsStringMap props;
1635  props["font"] = mFontFamily;
1636  props["chr"] = mChr;
1637  props["size"] = QString::number( mSize );
1638  props["size_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mSizeUnit );
1639  props["size_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mSizeMapUnitScale );
1640  props["color"] = QgsSymbolLayerV2Utils::encodeColor( mColor );
1641  props["angle"] = QString::number( mAngle );
1642  props["offset"] = QgsSymbolLayerV2Utils::encodePoint( mOffset );
1643  props["offset_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mOffsetUnit );
1644  props["offset_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOffsetMapUnitScale );
1645  props["horizontal_anchor_point"] = QString::number( mHorizontalAnchorPoint );
1646  props["vertical_anchor_point"] = QString::number( mVerticalAnchorPoint );
1647  return props;
1648 }
1649 
1651 {
1653  m->setOffset( mOffset );
1654  m->setOffsetUnit( mOffsetUnit );
1656  m->setSizeUnit( mSizeUnit );
1660  return m;
1661 }
1662 
1663 void QgsFontMarkerSymbolLayerV2::writeSldMarker( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const
1664 {
1665  // <Graphic>
1666  QDomElement graphicElem = doc.createElement( "se:Graphic" );
1667  element.appendChild( graphicElem );
1668 
1669  QString fontPath = QString( "ttf://%1" ).arg( mFontFamily );
1670  int markIndex = mChr.unicode();
1671  QgsSymbolLayerV2Utils::externalMarkerToSld( doc, graphicElem, fontPath, "ttf", &markIndex, mColor, mSize );
1672 
1673  // <Rotation>
1674  QString angleFunc;
1675  bool ok;
1676  double angle = props.value( "angle", "0" ).toDouble( &ok );
1677  if ( !ok )
1678  {
1679  angleFunc = QString( "%1 + %2" ).arg( props.value( "angle", "0" ) ).arg( mAngle );
1680  }
1681  else if ( angle + mAngle != 0 )
1682  {
1683  angleFunc = QString::number( angle + mAngle );
1684  }
1685  QgsSymbolLayerV2Utils::createRotationElement( doc, graphicElem, angleFunc );
1686 
1687  // <Displacement>
1689 }
1690 
1692 {
1693  QgsDebugMsg( "Entered." );
1694 
1695  QDomElement graphicElem = element.firstChildElement( "Graphic" );
1696  if ( graphicElem.isNull() )
1697  return NULL;
1698 
1699  QString name, format;
1700  QColor color;
1701  double size;
1702  int chr;
1703 
1704  if ( !QgsSymbolLayerV2Utils::externalMarkerFromSld( graphicElem, name, format, chr, color, size ) )
1705  return NULL;
1706 
1707  if ( !name.startsWith( "ttf://" ) || format != "ttf" )
1708  return NULL;
1709 
1710  QString fontFamily = name.mid( 6 );
1711 
1712  double angle = 0.0;
1713  QString angleFunc;
1714  if ( QgsSymbolLayerV2Utils::rotationFromSldElement( graphicElem, angleFunc ) )
1715  {
1716  bool ok;
1717  double d = angleFunc.toDouble( &ok );
1718  if ( ok )
1719  angle = d;
1720  }
1721 
1722  QPointF offset;
1724 
1725  QgsMarkerSymbolLayerV2 *m = new QgsFontMarkerSymbolLayerV2( fontFamily, chr, size, color );
1726  m->setAngle( angle );
1727  m->setOffset( offset );
1728  return m;
1729 }
1730 
1731 
QString ogrFeatureStyle(double mmScaleFactor, double mapUnitScaleFactor) const
static QString encodeOutputUnit(QgsSymbolV2::OutputUnit unit)
Q_GUI_EXPORT int qt_defaultDpiX()
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:89
void setOutlineStyle(Qt::PenStyle outlineStyle)
QgsSymbolLayerV2 * clone() const
void setOutputUnit(QgsSymbolV2::OutputUnit unit)
static void multiplyImageOpacity(QImage *image, qreal alpha)
Multiplies opacity of image pixel values with a (global) transparency value.
int renderHints() const
Definition: qgssymbolv2.h:187
QgsMapUnitScale mSizeMapUnitScale
Q_GUI_EXPORT int qt_defaultDpiY()
QgsSymbolV2::OutputUnit outputUnit() const
static Q_DECL_DEPRECATED bool wellKnownMarkerFromSld(QDomElement &element, QString &name, QColor &color, QColor &borderColor, double &borderWidth, double &size)
void startRender(QgsSymbolV2RenderContext &context)
void setMapUnitScale(const QgsMapUnitScale &scale)
#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&.
QVariant evaluate(const QgsFeature *f=NULL)
Evaluate the feature and return the result.
QColor selectionColor() const
Added in QGIS v2.0.
QgsSymbolV2::OutputUnit mOutlineWidthUnit
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
#define DEFAULT_SIMPLEMARKER_ANGLE
void startRender(QgsSymbolV2RenderContext &context)
void renderPoint(const QPointF &point, QgsSymbolV2RenderContext &context)
void writeSldMarker(QDomDocument &doc, QDomElement &element, QgsStringMap props) const
void setFillColor(const QColor &c)
Set fill color.
static void createRotationElement(QDomDocument &doc, QDomElement &element, QString rotationFunc)
double rendererScale() const
void stopRender(QgsSymbolV2RenderContext &context)
#define DEFAULT_FONTMARKER_CHR
void setMapUnitScale(const QgsMapUnitScale &scale)
void setOffset(QPointF offset)
void setHorizontalAnchorPoint(HorizontalAnchorPoint h)
QgsMapUnitScale mapUnitScale() const
#define DEG2RAD(x)
#define DEFAULT_SIMPLEMARKER_COLOR
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)
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
double scaleFactor() const
void writeSldMarker(QDomDocument &doc, QDomElement &element, QgsStringMap props) const
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:113
static void _fixQPictureDPI(QPainter *p)
void setOffsetMapUnitScale(const QgsMapUnitScale &scale)
static void createDisplacementElement(QDomDocument &doc, QDomElement &element, QPointF offset)
void setOutputUnit(QgsSymbolV2::OutputUnit unit)
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
QMap< QString, QString > QgsStringMap
Definition: qgis.h:416
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Definition: qgis.h:324
static QgsSymbolLayerV2 * createFromSld(QDomElement &element)
#define DEFAULT_SVGMARKER_ANGLE
void setOffsetUnit(QgsSymbolV2::OutputUnit unit)
void startRender(QgsSymbolV2RenderContext &context)
void setMapUnitScale(const QgsMapUnitScale &scale)
static QString encodeColor(QColor color)
#define DEFAULT_SIMPLEMARKER_NAME
virtual QgsExpression * expression(const QString &property) const
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:179
void drawMarker(QPainter *p, QgsSymbolV2RenderContext &context)
static QgsSvgCache * instance()
Definition: qgssvgcache.cpp:84
static QString encodePenStyle(Qt::PenStyle style)
void setOutlineWidthUnit(QgsSymbolV2::OutputUnit unit)
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)
static QString symbolPathToName(QString path)
Get symbols's name from its path.
void setOutlineWidthUnit(QgsSymbolV2::OutputUnit u)
void setOutputUnit(QgsSymbolV2::OutputUnit unit)
const QgsFeature * feature() const
Current feature being rendered - may be null.
Definition: qgssymbolv2.h:193
static QString encodePoint(QPointF point)
QColor fillColor() const
Get fill color.
static Qt::PenStyle decodePenStyle(QString str)
#define DEFAULT_SCALE_METHOD
QgsSymbolV2::ScaleMethod mScaleMethod
static QString symbolNameToPath(QString name)
Get symbol's path from its name.
bool forceVectorOutput() const
void setSizeUnit(QgsSymbolV2::OutputUnit unit)
static bool externalMarkerFromSld(QDomElement &element, QString &path, QString &format, int &markIndex, QColor &color, double &size)
void startRender(QgsSymbolV2RenderContext &context)
double rasterScaleFactor() const
#define DEFAULT_FONTMARKER_ANGLE
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)
void setOutlineWidthMapUnitScale(const QgsMapUnitScale &scale)
A class to represent a point geometry.
Definition: qgspoint.h:63
QgsSymbolV2::ScaleMethod scaleMethod() const
QgsMapUnitScale mapUnitScale() const
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)
QgsSymbolLayerV2 * clone() const
void renderPoint(const QPointF &point, QgsSymbolV2RenderContext &context)
void writeSldMarker(QDomDocument &doc, QDomElement &element, QgsStringMap props) const
bool writeDxf(QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, const QgsSymbolV2RenderContext *context, const QgsFeature *f, const QPointF &shift=QPointF(0.0, 0.0)) const
void setOutlineWidthMapUnitScale(const QgsMapUnitScale &scale)
QColor outlineColor() const
Get outline color.
#define DEFAULT_FONTMARKER_SIZE
#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.
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
void stopRender(QgsSymbolV2RenderContext &context)
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)
virtual const QgsExpression * dataDefinedProperty(const QString &property) const
static QString encodeScaleMethod(QgsSymbolV2::ScaleMethod scaleMethod)
QgsRenderContext & renderContext()
Definition: qgssymbolv2.h:168
bool preparePath(QString name=QString())
static void externalGraphicToSld(QDomDocument &doc, QDomElement &element, QString path, QString mime, QColor color, double size=-1)
QgsMapUnitScale mapUnitScale() const
QgsSymbolV2::OutputUnit outputUnit() const
static Q_DECL_DEPRECATED void wellKnownMarkerToSld(QDomDocument &doc, QDomElement &element, QString name, QColor color, QColor borderColor=QColor(), double borderWidth=-1, double size=-1)
const QgsFields * fields() const
Fields of the layer.
Definition: qgssymbolv2.h:199
QgsSymbolV2::OutputUnit mOffsetUnit
static bool rotationFromSldElement(QDomElement &element, QString &rotationFunc)
QgsSymbolLayerV2 * clone() const
bool selected() const
Definition: qgssymbolv2.h:183
QgsSymbolV2::OutputUnit outputUnit() const
static QgsSymbolV2::ScaleMethod decodeScaleMethod(QString str)
VerticalAnchorPoint mVerticalAnchorPoint
bool prepareShape(QString name=QString())
QgsSymbolV2::OutputUnit mSizeUnit
QgsMapUnitScale mOffsetMapUnitScale
void setOutlineColor(const QColor &c)
Set outline color.
void stopRender(QgsSymbolV2RenderContext &context)
void markerOffset(const QgsSymbolV2RenderContext &context, double &offsetX, double &offsetY) const
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
void setAngle(double angle)
bool writeDxf(QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, const QgsSymbolV2RenderContext *context, const QgsFeature *f, const QPointF &shift=QPointF(0.0, 0.0)) const
double size
Definition: qgssvgcache.cpp:77
static QgsSymbolLayerV2 * createFromSld(QDomElement &element)
void saveDataDefinedProperties(QgsStringMap &stringMap) const
Saves data defined properties to string map.
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
bool prepareCache(QgsSymbolV2RenderContext &context)
Prepares cache image.
static QgsSymbolV2::OutputUnit decodeOutputUnit(QString str)
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 data defined properties of this layer to another symbol layer.
void renderPoint(const QPointF &point, QgsSymbolV2RenderContext &context)
virtual void setDataDefinedProperty(const QString &property, const QString &expressionString)
static QPointF _rotatedOffset(const QPointF &offset, double angle)
#define DEFAULT_SIMPLEMARKER_BORDERCOLOR