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