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