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