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