QGIS API Documentation  2.12.0-Lyon
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( const QString& name, const QColor& color, const 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  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 );
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  context.setOriginalValueVariable( mSize );
478  }
479 
480  if ( hasDataDefinedSize && ok )
481  {
482  switch ( mScaleMethod )
483  {
485  scaledSize = sqrt( scaledSize );
486  break;
488  break;
489  }
490  }
491 
492  //offset
493  double offsetX = 0;
494  double offsetY = 0;
495  markerOffset( context, scaledSize, scaledSize, offsetX, offsetY );
496  QPointF off( offsetX, offsetY );
497 
498  //angle
499  double angle = mAngle + mLineAngle;
500  bool usingDataDefinedRotation = false;
502  {
503  context.setOriginalValueVariable( angle );
505  usingDataDefinedRotation = ok;
506  }
507 
508  bool hasDataDefinedRotation = context.renderHints() & QgsSymbolV2::DataDefinedRotation || usingDataDefinedRotation;
509  if ( hasDataDefinedRotation )
510  {
511  // For non-point markers, "dataDefinedRotation" means following the
512  // shape (shape-data defined). For them, "field-data defined" does
513  // not work at all. TODO: if "field-data defined" ever gets implemented
514  // we'll need a way to distinguish here between the two, possibly
515  // using another flag in renderHints()
516  const QgsFeature* f = context.feature();
517  if ( f )
518  {
519  const QgsGeometry *g = f->constGeometry();
520  if ( g && g->type() == QGis::Point )
521  {
522  const QgsMapToPixel& m2p = context.renderContext().mapToPixel();
523  angle += m2p.mapRotation();
524  }
525  }
526  }
527 
528  if ( angle )
529  off = _rotatedOffset( off, angle );
530 
531  //data defined shape?
532  bool createdNewPath = false;
534  {
535  context.setOriginalValueVariable( mName );
537  if ( ok )
538  {
539  if ( !prepareShape( name ) ) // drawing as a polygon
540  {
541  preparePath( name ); // drawing as a painter path
542  }
543  createdNewPath = true;
544  }
545  }
546 
547  if ( mUsingCache )
548  {
549  //QgsDebugMsg( QString("XXX using cache") );
550  // we will use cached image
551  QImage &img = context.selected() ? mSelCache : mCache;
552  double s = img.width() / context.renderContext().rasterScaleFactor();
553  p->drawImage( QRectF( point.x() - s / 2.0 + off.x(),
554  point.y() - s / 2.0 + off.y(),
555  s, s ), img );
556  }
557  else
558  {
559  QMatrix transform;
560 
561  // move to the desired position
562  transform.translate( point.x() + off.x(), point.y() + off.y() );
563 
564  // resize if necessary
565  if ( hasDataDefinedSize || createdNewPath )
566  {
568  double half = s / 2.0;
569  transform.scale( half, half );
570  }
571 
572  if ( angle != 0 && ( hasDataDefinedRotation || createdNewPath ) )
573  transform.rotate( angle );
574 
576  {
579  if ( ok )
581  }
583  {
586  if ( ok )
587  {
590  }
591  }
593  {
596  if ( ok )
597  {
600  }
601  }
603  {
606  if ( ok )
607  {
610  }
611  }
612 
613  p->setBrush( context.selected() ? mSelBrush : mBrush );
614  p->setPen( context.selected() ? mSelPen : mPen );
615 
616  if ( !mPolygon.isEmpty() )
617  p->drawPolygon( transform.map( mPolygon ) );
618  else
619  p->drawPath( transform.map( mPath ) );
620  }
621 }
622 
623 
625 {
626  QgsStringMap map;
627  map["name"] = mName;
628  map["color"] = QgsSymbolLayerV2Utils::encodeColor( mColor );
629  map["outline_color"] = QgsSymbolLayerV2Utils::encodeColor( mBorderColor );
630  map["size"] = QString::number( mSize );
632  map["size_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mSizeMapUnitScale );
633  map["angle"] = QString::number( mAngle );
634  map["offset"] = QgsSymbolLayerV2Utils::encodePoint( mOffset );
636  map["offset_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOffsetMapUnitScale );
638  map["outline_style"] = QgsSymbolLayerV2Utils::encodePenStyle( mOutlineStyle );
639  map["outline_width"] = QString::number( mOutlineWidth );
640  map["outline_width_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mOutlineWidthUnit );
641  map["outline_width_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOutlineWidthMapUnitScale );
642  map["horizontal_anchor_point"] = QString::number( mHorizontalAnchorPoint );
643  map["vertical_anchor_point"] = QString::number( mVerticalAnchorPoint );
644 
645 
646  //data define properties
648  return map;
649 }
650 
652 {
654  m->setOffset( mOffset );
655  m->setSizeUnit( mSizeUnit );
666  copyPaintEffect( m );
667  return m;
668 }
669 
671 {
672  // <Graphic>
673  QDomElement graphicElem = doc.createElement( "se:Graphic" );
674  element.appendChild( graphicElem );
675 
677 
678  // <Rotation>
679  QString angleFunc;
680  bool ok;
681  double angle = props.value( "angle", "0" ).toDouble( &ok );
682  if ( !ok )
683  {
684  angleFunc = QString( "%1 + %2" ).arg( props.value( "angle", "0" ) ).arg( mAngle );
685  }
686  else if ( angle + mAngle != 0 )
687  {
688  angleFunc = QString::number( angle + mAngle );
689  }
690  QgsSymbolLayerV2Utils::createRotationElement( doc, graphicElem, angleFunc );
691 
692  // <Displacement>
694 }
695 
696 QString QgsSimpleMarkerSymbolLayerV2::ogrFeatureStyle( double mmScaleFactor, double mapUnitScaleFactor ) const
697 {
698  Q_UNUSED( mmScaleFactor );
699  Q_UNUSED( mapUnitScaleFactor );
700 #if 0
701  QString ogrType = "3"; //default is circle
702  if ( mName == "square" )
703  {
704  ogrType = "5";
705  }
706  else if ( mName == "triangle" )
707  {
708  ogrType = "7";
709  }
710  else if ( mName == "star" )
711  {
712  ogrType = "9";
713  }
714  else if ( mName == "circle" )
715  {
716  ogrType = "3";
717  }
718  else if ( mName == "cross" )
719  {
720  ogrType = "0";
721  }
722  else if ( mName == "x" || mName == "cross2" )
723  {
724  ogrType = "1";
725  }
726  else if ( mName == "line" )
727  {
728  ogrType = "10";
729  }
730 
731  QString ogrString;
732  ogrString.append( "SYMBOL(" );
733  ogrString.append( "id:" );
734  ogrString.append( "\"" );
735  ogrString.append( "ogr-sym-" );
736  ogrString.append( ogrType );
737  ogrString.append( "\"" );
738  ogrString.append( ",c:" );
739  ogrString.append( mColor.name() );
740  ogrString.append( ",o:" );
741  ogrString.append( mBorderColor.name() );
742  ogrString.append( QString( ",s:%1mm" ).arg( mSize ) );
743  ogrString.append( ")" );
744  return ogrString;
745 #endif //0
746 
747  QString ogrString;
748  ogrString.append( "PEN(" );
749  ogrString.append( "c:" );
750  ogrString.append( mColor.name() );
751  ogrString.append( ",w:" );
752  ogrString.append( QString::number( mSize ) );
753  ogrString.append( "mm" );
754  ogrString.append( ")" );
755  return ogrString;
756 }
757 
759 {
760  QgsDebugMsg( "Entered." );
761 
762  QDomElement graphicElem = element.firstChildElement( "Graphic" );
763  if ( graphicElem.isNull() )
764  return NULL;
765 
766  QString name = "square";
768  double borderWidth, size;
769  Qt::PenStyle borderStyle;
770 
771  if ( !QgsSymbolLayerV2Utils::wellKnownMarkerFromSld( graphicElem, name, color, borderColor, borderStyle, borderWidth, size ) )
772  return NULL;
773 
774  double angle = 0.0;
775  QString angleFunc;
776  if ( QgsSymbolLayerV2Utils::rotationFromSldElement( graphicElem, angleFunc ) )
777  {
778  bool ok;
779  double d = angleFunc.toDouble( &ok );
780  if ( ok )
781  angle = d;
782  }
783 
784  QPointF offset;
786 
787  QgsSimpleMarkerSymbolLayerV2 *m = new QgsSimpleMarkerSymbolLayerV2( name, color, borderColor, size );
788  m->setAngle( angle );
789  m->setOffset( offset );
790  m->setOutlineStyle( borderStyle );
791  return m;
792 }
793 
795 {
796  Q_UNUSED( context );
797 
798  if ( mPolygon.count() != 0 )
799  {
800  p->drawPolygon( mPolygon );
801  }
802  else
803  {
804  p->drawPath( mPath );
805  }
806 }
807 
808 bool QgsSimpleMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, QgsSymbolV2RenderContext *context, const QgsFeature*, const QPointF& shift ) const
809 {
810  //data defined size?
811  double size = mSize;
812 
813  bool hasDataDefinedSize = false;
814  if ( context )
815  {
817  }
818 
819  //data defined size
820  bool ok = true;
821  if ( hasDataDefinedSize )
822  {
824  {
825  context->setOriginalValueVariable( mSize );
827  }
828 
829  if ( ok )
830  {
831  switch ( mScaleMethod )
832  {
834  size = sqrt( size );
835  break;
837  break;
838  }
839  }
840 
842  }
843  if ( mSizeUnit == QgsSymbolV2::MM )
844  {
845  size *= mmMapUnitScaleFactor;
846  }
847  double halfSize = size / 2.0;
848 
849  //outlineWidth
850  double outlineWidth = mOutlineWidth;
851 
853  {
856  }
857  if ( mSizeUnit == QgsSymbolV2::MM )
858  {
859  outlineWidth *= mmMapUnitScaleFactor;
860  }
861 
862  //color
863  QColor pc = mPen.color();
864  QColor bc = mBrush.color();
866  {
869  if ( ok )
870  bc = QgsSymbolLayerV2Utils::decodeColor( colorString );
871  }
873  {
876  if ( ok )
877  pc = QgsSymbolLayerV2Utils::decodeColor( colorString );
878  }
879 
880  //offset
881  double offsetX = 0;
882  double offsetY = 0;
883  if ( context )
884  {
885  markerOffset( *context, offsetX, offsetY );
886  }
887  QPointF off( offsetX, offsetY );
888 
889  //angle
890  double angle = mAngle + mLineAngle;
892  {
893  context->setOriginalValueVariable( mAngle );
895  }
896 
897  QString name( mName );
899  {
900  context->setOriginalValueVariable( mName );
902  }
903 
904  angle = -angle; //rotation in Qt is counterclockwise
905  if ( angle )
906  off = _rotatedOffset( off, angle );
907 
908  if ( mSizeUnit == QgsSymbolV2::MM )
909  {
910  off *= mmMapUnitScaleFactor;
911  }
912 
913  QTransform t;
914  t.translate( shift.x() + offsetX, shift.y() + offsetY );
915 
916  if ( angle != 0 )
917  t.rotate( angle );
918 
919  QPolygonF polygon;
920  if ( prepareShape( name, polygon ) )
921  {
922  t.scale( halfSize, -halfSize );
923 
924  polygon = t.map( polygon );
925 
926  QgsPolygon p( 1 );
927  p.resize( 1 );
928  p[0].resize( polygon.size() + 1 );
929  int i = 0;
930  for ( i = 0; i < polygon.size(); i++ )
931  p[0][i] = polygon[i];
932  p[0][i] = p[0][0];
933 
934  if ( mBrush.style() != Qt::NoBrush )
935  e.writePolygon( p, layerName, "SOLID", bc );
936  if ( mPen.style() != Qt::NoPen )
937  e.writePolyline( p[0], layerName, "CONTINUOUS", pc, outlineWidth );
938  }
939  else if ( name == "circle" )
940  {
941  if ( mBrush.style() != Qt::NoBrush )
942  e.writeFilledCircle( layerName, bc, shift, halfSize );
943  if ( mPen.style() != Qt::NoPen )
944  e.writeCircle( layerName, pc, shift, halfSize, "CONTINUOUS", outlineWidth );
945  }
946  else if ( name == "line" )
947  {
948  QPointF pt1 = t.map( QPointF( 0, -halfSize ) );
949  QPointF pt2 = t.map( QPointF( 0, halfSize ) );
950 
951  if ( mPen.style() != Qt::NoPen )
952  e.writeLine( pt1, pt2, layerName, "CONTINUOUS", pc, outlineWidth );
953  }
954  else if ( name == "cross" )
955  {
956  if ( mPen.style() != Qt::NoPen )
957  {
958  QPointF pt1 = t.map( QPointF( -halfSize, 0 ) );
959  QPointF pt2 = t.map( QPointF( halfSize, 0 ) );
960  QPointF pt3 = t.map( QPointF( 0, -halfSize ) );
961  QPointF pt4 = t.map( QPointF( 0, 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 == "x" || name == "cross2" )
968  {
969  if ( mPen.style() != Qt::NoPen )
970  {
971  QPointF pt1 = t.map( QPointF( -halfSize, -halfSize ) );
972  QPointF pt2 = t.map( QPointF( halfSize, halfSize ) );
973  QPointF pt3 = t.map( QPointF( halfSize, -halfSize ) );
974  QPointF pt4 = t.map( QPointF( -halfSize, halfSize ) );
975 
976  e.writeLine( pt1, pt2, layerName, "CONTINUOUS", pc, outlineWidth );
977  e.writeLine( pt3, pt4, layerName, "CONTINUOUS", pc, outlineWidth );
978  }
979  }
980  else if ( name == "arrowhead" )
981  {
982  if ( mPen.style() != Qt::NoPen )
983  {
984  QPointF pt1 = t.map( QPointF( -halfSize, halfSize ) );
985  QPointF pt2 = t.map( QPointF( 0, 0 ) );
986  QPointF pt3 = t.map( QPointF( -halfSize, -halfSize ) );
987 
988  e.writeLine( pt1, pt2, layerName, "CONTINUOUS", pc, outlineWidth );
989  e.writeLine( pt3, pt2, layerName, "CONTINUOUS", pc, outlineWidth );
990  }
991  }
992  else
993  {
994  QgsDebugMsg( QString( "Unsupported dxf marker name %1" ).arg( name ) );
995  return false;
996  }
997 
998  return true;
999 }
1000 
1001 
1003 {
1005  mOutlineWidthUnit = unit;
1006 }
1007 
1009 {
1011  {
1012  return mOutlineWidthUnit;
1013  }
1014  return QgsSymbolV2::Mixed;
1015 }
1016 
1018 {
1020  mOutlineWidthMapUnitScale = scale;
1021 }
1022 
1024 {
1026  {
1028  }
1029  return QgsMapUnitScale();
1030 }
1031 
1033 
1034 
1036 {
1038  mSize = size;
1039  mAngle = angle;
1040  mOffset = QPointF( 0, 0 );
1042  mOutlineWidth = 0.2;
1044  mColor = QColor( Qt::black );
1045  mOutlineColor = QColor( Qt::black );
1046 }
1047 
1048 
1050 {
1052  double size = DEFAULT_SVGMARKER_SIZE;
1053  double angle = DEFAULT_SVGMARKER_ANGLE;
1055 
1056  if ( props.contains( "name" ) )
1057  name = props["name"];
1058  if ( props.contains( "size" ) )
1059  size = props["size"].toDouble();
1060  if ( props.contains( "angle" ) )
1061  angle = props["angle"].toDouble();
1062  if ( props.contains( "scale_method" ) )
1063  scaleMethod = QgsSymbolLayerV2Utils::decodeScaleMethod( props["scale_method"] );
1064 
1065  QgsSvgMarkerSymbolLayerV2* m = new QgsSvgMarkerSymbolLayerV2( name, size, angle, scaleMethod );
1066 
1067  //we only check the svg default parameters if necessary, since it could be expensive
1068  if ( !props.contains( "fill" ) && !props.contains( "color" ) && !props.contains( "outline" ) &&
1069  !props.contains( "outline_color" ) && !props.contains( "outline-width" ) && !props.contains( "outline_width" ) )
1070  {
1072  double outlineWidth;
1073  bool hasFillParam = false, hasOutlineParam = false, hasOutlineWidthParam = false;
1074  bool hasDefaultFillColor = false, hasDefaultOutlineColor = false, hasDefaultOutlineWidth = false;
1075  QgsSvgCache::instance()->containsParams( name, hasFillParam, hasDefaultFillColor, fillColor,
1076  hasOutlineParam, hasDefaultOutlineColor, outlineColor,
1077  hasOutlineWidthParam, hasDefaultOutlineWidth, outlineWidth );
1078  if ( hasDefaultFillColor )
1079  {
1080  m->setFillColor( fillColor );
1081  }
1082  if ( hasDefaultOutlineColor )
1083  {
1084  m->setOutlineColor( outlineColor );
1085  }
1086  if ( hasDefaultOutlineWidth )
1087  {
1088  m->setOutlineWidth( outlineWidth );
1089  }
1090  }
1091 
1092  if ( props.contains( "size_unit" ) )
1093  m->setSizeUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["size_unit"] ) );
1094  if ( props.contains( "size_map_unit_scale" ) )
1095  m->setSizeMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( props["size_map_unit_scale"] ) );
1096  if ( props.contains( "offset" ) )
1097  m->setOffset( QgsSymbolLayerV2Utils::decodePoint( props["offset"] ) );
1098  if ( props.contains( "offset_unit" ) )
1099  m->setOffsetUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["offset_unit"] ) );
1100  if ( props.contains( "offset_map_unit_scale" ) )
1101  m->setOffsetMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( props["offset_map_unit_scale"] ) );
1102  if ( props.contains( "fill" ) )
1103  {
1104  //pre 2.5 projects used "fill"
1105  m->setFillColor( QgsSymbolLayerV2Utils::decodeColor( props["fill"] ) );
1106  }
1107  else if ( props.contains( "color" ) )
1108  {
1109  m->setFillColor( QgsSymbolLayerV2Utils::decodeColor( props["color"] ) );
1110  }
1111  if ( props.contains( "outline" ) )
1112  {
1113  //pre 2.5 projects used "outline"
1114  m->setOutlineColor( QgsSymbolLayerV2Utils::decodeColor( props["outline"] ) );
1115  }
1116  else if ( props.contains( "outline_color" ) )
1117  {
1118  m->setOutlineColor( QgsSymbolLayerV2Utils::decodeColor( props["outline_color"] ) );
1119  }
1120  else if ( props.contains( "line_color" ) )
1121  {
1122  m->setOutlineColor( QgsSymbolLayerV2Utils::decodeColor( props["line_color"] ) );
1123  }
1124 
1125  if ( props.contains( "outline-width" ) )
1126  {
1127  //pre 2.5 projects used "outline-width"
1128  m->setOutlineWidth( props["outline-width"].toDouble() );
1129  }
1130  else if ( props.contains( "outline_width" ) )
1131  {
1132  m->setOutlineWidth( props["outline_width"].toDouble() );
1133  }
1134  else if ( props.contains( "line_width" ) )
1135  {
1136  m->setOutlineWidth( props["line_width"].toDouble() );
1137  }
1138 
1139  if ( props.contains( "outline_width_unit" ) )
1140  {
1141  m->setOutlineWidthUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["outline_width_unit"] ) );
1142  }
1143  else if ( props.contains( "line_width_unit" ) )
1144  {
1145  m->setOutlineWidthUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["line_width_unit"] ) );
1146  }
1147  if ( props.contains( "outline_width_map_unit_scale" ) )
1148  m->setOutlineWidthMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( props["outline_width_map_unit_scale"] ) );
1149 
1150  if ( props.contains( "horizontal_anchor_point" ) )
1151  {
1152  m->setHorizontalAnchorPoint( QgsMarkerSymbolLayerV2::HorizontalAnchorPoint( props[ "horizontal_anchor_point" ].toInt() ) );
1153  }
1154  if ( props.contains( "vertical_anchor_point" ) )
1155  {
1156  m->setVerticalAnchorPoint( QgsMarkerSymbolLayerV2::VerticalAnchorPoint( props[ "vertical_anchor_point" ].toInt() ) );
1157  }
1158 
1159  m->restoreDataDefinedProperties( props );
1160 
1161  return m;
1162 }
1163 
1165 {
1166  mPath = path;
1168  double outlineWidth;
1169  bool hasFillParam = false, hasOutlineParam = false, hasOutlineWidthParam = false;
1170  bool hasDefaultFillColor = false, hasDefaultOutlineColor = false, hasDefaultOutlineWidth = false;
1171  QgsSvgCache::instance()->containsParams( path, hasFillParam, hasDefaultFillColor, fillColor,
1172  hasOutlineParam, hasDefaultOutlineColor, outlineColor,
1173  hasOutlineWidthParam, hasDefaultOutlineWidth, outlineWidth );
1174  if ( hasDefaultFillColor )
1175  {
1176  setFillColor( fillColor );
1177  }
1178  if ( hasDefaultOutlineColor )
1179  {
1180  setOutlineColor( outlineColor );
1181  }
1182  if ( hasDefaultOutlineWidth )
1183  {
1184  setOutlineWidth( outlineWidth );
1185  }
1186 }
1187 
1188 
1190 {
1191  return "SvgMarker";
1192 }
1193 
1195 {
1196  QgsMarkerSymbolLayerV2::startRender( context ); // get anchor point expressions
1197  Q_UNUSED( context );
1198  prepareExpressions( context );
1199 }
1200 
1202 {
1203  Q_UNUSED( context );
1204 }
1205 
1207 {
1208  QPainter *p = context.renderContext().painter();
1209  if ( !p )
1210  return;
1211 
1212  double scaledSize = mSize;
1213 
1215 
1216  bool ok = true;
1218  {
1219  context.setOriginalValueVariable( mSize );
1220  scaledSize = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_SIZE, context, mSize, &ok ).toDouble();
1221  }
1222 
1223  if ( hasDataDefinedSize && ok )
1224  {
1225  switch ( mScaleMethod )
1226  {
1228  scaledSize = sqrt( scaledSize );
1229  break;
1231  break;
1232  }
1233  }
1234 
1236 
1237  //don't render symbols with size below one or above 10,000 pixels
1238  if (( int )size < 1 || 10000.0 < size )
1239  {
1240  return;
1241  }
1242 
1243  p->save();
1244 
1245  //offset
1246  double offsetX = 0;
1247  double offsetY = 0;
1248  markerOffset( context, scaledSize, scaledSize, offsetX, offsetY );
1249  QPointF outputOffset( offsetX, offsetY );
1250 
1251  double angle = mAngle + mLineAngle;
1253  {
1254  context.setOriginalValueVariable( mAngle );
1256  }
1257 
1259  if ( hasDataDefinedRotation )
1260  {
1261  // For non-point markers, "dataDefinedRotation" means following the
1262  // shape (shape-data defined). For them, "field-data defined" does
1263  // not work at all. TODO: if "field-data defined" ever gets implemented
1264  // we'll need a way to distinguish here between the two, possibly
1265  // using another flag in renderHints()
1266  const QgsFeature* f = context.feature();
1267  if ( f )
1268  {
1269  const QgsGeometry *g = f->constGeometry();
1270  if ( g && g->type() == QGis::Point )
1271  {
1272  const QgsMapToPixel& m2p = context.renderContext().mapToPixel();
1273  angle += m2p.mapRotation();
1274  }
1275  }
1276  }
1277 
1278  if ( angle )
1279  outputOffset = _rotatedOffset( outputOffset, angle );
1280  p->translate( point + outputOffset );
1281 
1282  bool rotated = !qgsDoubleNear( angle, 0 );
1283  if ( rotated )
1284  p->rotate( angle );
1285 
1286  QString path = mPath;
1288  {
1289  context.setOriginalValueVariable( mPath );
1291  }
1292 
1293  double outlineWidth = mOutlineWidth;
1295  {
1298  }
1300 
1303  {
1306  if ( ok )
1307  fillColor = QgsSymbolLayerV2Utils::decodeColor( colorString );
1308  }
1309 
1312  {
1315  if ( ok )
1316  outlineColor = QgsSymbolLayerV2Utils::decodeColor( colorString );
1317  }
1318 
1319  bool fitsInCache = true;
1320  bool usePict = true;
1321  double hwRatio = 1.0;
1322  if ( !context.renderContext().forceVectorOutput() && !rotated )
1323  {
1324  usePict = false;
1325  const QImage& img = QgsSvgCache::instance()->svgAsImage( path, size, fillColor, outlineColor, outlineWidth,
1326  context.renderContext().scaleFactor(), context.renderContext().rasterScaleFactor(), fitsInCache );
1327  if ( fitsInCache && img.width() > 1 )
1328  {
1329  //consider transparency
1330  if ( !qgsDoubleNear( context.alpha(), 1.0 ) )
1331  {
1332  QImage transparentImage = img.copy();
1333  QgsSymbolLayerV2Utils::multiplyImageOpacity( &transparentImage, context.alpha() );
1334  p->drawImage( -transparentImage.width() / 2.0, -transparentImage.height() / 2.0, transparentImage );
1335  hwRatio = ( double )transparentImage.height() / ( double )transparentImage.width();
1336  }
1337  else
1338  {
1339  p->drawImage( -img.width() / 2.0, -img.height() / 2.0, img );
1340  hwRatio = ( double )img.height() / ( double )img.width();
1341  }
1342  }
1343  }
1344 
1345  if ( usePict || !fitsInCache )
1346  {
1347  p->setOpacity( context.alpha() );
1348  const QPicture& pct = QgsSvgCache::instance()->svgAsPicture( path, size, fillColor, outlineColor, outlineWidth,
1350 
1351  if ( pct.width() > 1 )
1352  {
1353  p->save();
1354  _fixQPictureDPI( p );
1355  p->drawPicture( 0, 0, pct );
1356  p->restore();
1357  hwRatio = ( double )pct.height() / ( double )pct.width();
1358  }
1359  }
1360 
1361  if ( context.selected() )
1362  {
1363  QPen pen( context.renderContext().selectionColor() );
1365  if ( penWidth > size / 20 )
1366  {
1367  // keep the pen width from covering symbol
1368  penWidth = size / 20;
1369  }
1370  double penOffset = penWidth / 2;
1371  pen.setWidth( penWidth );
1372  p->setPen( pen );
1373  p->setBrush( Qt::NoBrush );
1374  double wSize = size + penOffset;
1375  double hSize = size * hwRatio + penOffset;
1376  p->drawRect( QRectF( -wSize / 2.0, -hSize / 2.0, wSize, hSize ) );
1377  }
1378 
1379  p->restore();
1380 }
1381 
1382 
1384 {
1385  QgsStringMap map;
1387  map["size"] = QString::number( mSize );
1388  map["size_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mSizeUnit );
1389  map["size_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mSizeMapUnitScale );
1390  map["angle"] = QString::number( mAngle );
1391  map["offset"] = QgsSymbolLayerV2Utils::encodePoint( mOffset );
1392  map["offset_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mOffsetUnit );
1393  map["offset_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOffsetMapUnitScale );
1394  map["scale_method"] = QgsSymbolLayerV2Utils::encodeScaleMethod( mScaleMethod );
1395  map["color"] = QgsSymbolLayerV2Utils::encodeColor( mColor );
1396  map["outline_color"] = QgsSymbolLayerV2Utils::encodeColor( mOutlineColor );
1397  map["outline_width"] = QString::number( mOutlineWidth );
1398  map["outline_width_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mOutlineWidthUnit );
1399  map["outline_width_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOutlineWidthMapUnitScale );
1400  map["horizontal_anchor_point"] = QString::number( mHorizontalAnchorPoint );
1401  map["vertical_anchor_point"] = QString::number( mVerticalAnchorPoint );
1402 
1404  return map;
1405 }
1406 
1408 {
1410  m->setColor( mColor );
1415  m->setOffset( mOffset );
1416  m->setOffsetUnit( mOffsetUnit );
1418  m->setSizeUnit( mSizeUnit );
1423  copyPaintEffect( m );
1424  return m;
1425 }
1426 
1428 {
1430  mOutlineWidthUnit = unit;
1431 }
1432 
1434 {
1436  if ( unit != mOutlineWidthUnit )
1437  {
1438  return QgsSymbolV2::Mixed;
1439  }
1440  return unit;
1441 }
1442 
1444 {
1446  mOutlineWidthMapUnitScale = scale;
1447 }
1448 
1450 {
1452  {
1454  }
1455  return QgsMapUnitScale();
1456 }
1457 
1459 {
1460  // <Graphic>
1461  QDomElement graphicElem = doc.createElement( "se:Graphic" );
1462  element.appendChild( graphicElem );
1463 
1464  QgsSymbolLayerV2Utils::externalGraphicToSld( doc, graphicElem, mPath, "image/svg+xml", mColor, mSize );
1465 
1466  // <Rotation>
1467  QString angleFunc;
1468  bool ok;
1469  double angle = props.value( "angle", "0" ).toDouble( &ok );
1470  if ( !ok )
1471  {
1472  angleFunc = QString( "%1 + %2" ).arg( props.value( "angle", "0" ) ).arg( mAngle );
1473  }
1474  else if ( angle + mAngle != 0 )
1475  {
1476  angleFunc = QString::number( angle + mAngle );
1477  }
1478 
1479  QgsSymbolLayerV2Utils::createRotationElement( doc, graphicElem, angleFunc );
1480 
1481  // <Displacement>
1483 }
1484 
1486 {
1487  QgsDebugMsg( "Entered." );
1488 
1489  QDomElement graphicElem = element.firstChildElement( "Graphic" );
1490  if ( graphicElem.isNull() )
1491  return NULL;
1492 
1493  QString path, mimeType;
1494  QColor fillColor;
1495  double size;
1496 
1497  if ( !QgsSymbolLayerV2Utils::externalGraphicFromSld( graphicElem, path, mimeType, fillColor, size ) )
1498  return NULL;
1499 
1500  if ( mimeType != "image/svg+xml" )
1501  return NULL;
1502 
1503  double angle = 0.0;
1504  QString angleFunc;
1505  if ( QgsSymbolLayerV2Utils::rotationFromSldElement( graphicElem, angleFunc ) )
1506  {
1507  bool ok;
1508  double d = angleFunc.toDouble( &ok );
1509  if ( ok )
1510  angle = d;
1511  }
1512 
1513  QPointF offset;
1515 
1517  m->setFillColor( fillColor );
1518  //m->setOutlineColor( outlineColor );
1519  //m->setOutlineWidth( outlineWidth );
1520  m->setAngle( angle );
1521  m->setOffset( offset );
1522  return m;
1523 }
1524 
1525 bool QgsSvgMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, QgsSymbolV2RenderContext *context, const QgsFeature*,
1526  const QPointF& shift ) const
1527 {
1528  Q_UNUSED( layerName );
1529  Q_UNUSED( shift ); //todo...
1530 
1531  //size
1532  double size = mSize;
1533 
1535 
1536  bool ok = true;
1538  {
1539  context->setOriginalValueVariable( mSize );
1541  }
1542 
1543  if ( hasDataDefinedSize && ok )
1544  {
1545  switch ( mScaleMethod )
1546  {
1548  size = sqrt( size );
1549  break;
1551  break;
1552  }
1553  }
1554 
1555  if ( mSizeUnit == QgsSymbolV2::MM )
1556  {
1557  size *= mmMapUnitScaleFactor;
1558  }
1559 
1560  double halfSize = size / 2.0;
1561 
1562  //offset, angle
1564 
1566  {
1569  if ( ok )
1570  offset = QgsSymbolLayerV2Utils::decodePoint( offsetString );
1571  }
1572  double offsetX = offset.x();
1573  double offsetY = offset.y();
1574  if ( mSizeUnit == QgsSymbolV2::MM )
1575  {
1576  offsetX *= mmMapUnitScaleFactor;
1577  offsetY *= mmMapUnitScaleFactor;
1578  }
1579 
1580  QPointF outputOffset( offsetX, offsetY );
1581 
1582  double angle = mAngle + mLineAngle;
1584  {
1585  context->setOriginalValueVariable( mAngle );
1587  }
1588  //angle = -angle; //rotation in Qt is counterclockwise
1589  if ( angle )
1590  outputOffset = _rotatedOffset( outputOffset, angle );
1591 
1592  QString path = mPath;
1594  {
1595  context->setOriginalValueVariable( mPath );
1597  }
1598 
1599  double outlineWidth = mOutlineWidth;
1601  {
1604  }
1606 
1609  {
1612  if ( ok )
1613  fillColor = QgsSymbolLayerV2Utils::decodeColor( colorString );
1614  }
1615 
1618  {
1621  if ( ok )
1622  outlineColor = QgsSymbolLayerV2Utils::decodeColor( colorString );
1623  }
1624 
1625  const QByteArray &svgContent = QgsSvgCache::instance()->svgContent( path, size, fillColor, outlineColor, outlineWidth,
1626  context->renderContext().scaleFactor(),
1627  context->renderContext().rasterScaleFactor() );
1628 
1629  //if current entry image is 0: cache image for entry
1630  // checks to see if image will fit into cache
1631  //update stats for memory usage
1632  QSvgRenderer r( svgContent );
1633  if ( !r.isValid() )
1634  {
1635  return false;
1636  }
1637 
1638  QgsDxfPaintDevice pd( &e );
1639  pd.setDrawingSize( QSizeF( r.defaultSize() ) );
1640 
1641  QPainter p;
1642  p.begin( &pd );
1643  if ( !qgsDoubleNear( angle, 0.0 ) )
1644  {
1645  p.translate( r.defaultSize().width() / 2.0, r.defaultSize().height() / 2.0 );
1646  p.rotate( angle );
1647  p.translate( -r.defaultSize().width() / 2.0, -r.defaultSize().height() / 2.0 );
1648  }
1649  pd.setShift( shift );
1650  pd.setOutputSize( QRectF( -halfSize, -halfSize, size, size ) );
1651  pd.setLayer( layerName );
1652  r.render( &p );
1653  p.end();
1654  return true;
1655 }
1656 
1658 
1659 QgsFontMarkerSymbolLayerV2::QgsFontMarkerSymbolLayerV2( const QString& fontFamily, QChar chr, double pointSize, const QColor& color, double angle )
1660  : mFontMetrics( 0 )
1661 {
1663  mChr = chr;
1664  mColor = color;
1665  mAngle = angle;
1666  mSize = pointSize;
1667  mOrigSize = pointSize;
1669  mOffset = QPointF( 0, 0 );
1671 }
1672 
1674 {
1675  delete mFontMetrics;
1676 }
1677 
1679 {
1682  double pointSize = DEFAULT_FONTMARKER_SIZE;
1685 
1686  if ( props.contains( "font" ) )
1687  fontFamily = props["font"];
1688  if ( props.contains( "chr" ) && props["chr"].length() > 0 )
1689  chr = props["chr"].at( 0 );
1690  if ( props.contains( "size" ) )
1691  pointSize = props["size"].toDouble();
1692  if ( props.contains( "color" ) )
1693  color = QgsSymbolLayerV2Utils::decodeColor( props["color"] );
1694  if ( props.contains( "angle" ) )
1695  angle = props["angle"].toDouble();
1696 
1697  QgsFontMarkerSymbolLayerV2* m = new QgsFontMarkerSymbolLayerV2( fontFamily, chr, pointSize, color, angle );
1698  if ( props.contains( "offset" ) )
1699  m->setOffset( QgsSymbolLayerV2Utils::decodePoint( props["offset"] ) );
1700  if ( props.contains( "offset_unit" ) )
1701  m->setOffsetUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["offset_unit" ] ) );
1702  if ( props.contains( "offset_map_unit_scale" ) )
1703  m->setOffsetMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( props["offset_map_unit_scale" ] ) );
1704  if ( props.contains( "size_unit" ) )
1705  m->setSizeUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["size_unit"] ) );
1706  if ( props.contains( "size_map_unit_scale" ) )
1707  m->setSizeMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( props["size_map_unit_scale"] ) );
1708  if ( props.contains( "horizontal_anchor_point" ) )
1709  {
1710  m->setHorizontalAnchorPoint( QgsMarkerSymbolLayerV2::HorizontalAnchorPoint( props[ "horizontal_anchor_point" ].toInt() ) );
1711  }
1712  if ( props.contains( "vertical_anchor_point" ) )
1713  {
1714  m->setVerticalAnchorPoint( QgsMarkerSymbolLayerV2::VerticalAnchorPoint( props[ "vertical_anchor_point" ].toInt() ) );
1715  }
1716 
1717  m->restoreDataDefinedProperties( props );
1718 
1719  return m;
1720 }
1721 
1723 {
1724  return "FontMarker";
1725 }
1726 
1728 {
1729  mFont = QFont( mFontFamily );
1731  delete mFontMetrics;
1732  mFontMetrics = new QFontMetrics( mFont );
1733  mChrOffset = QPointF( mFontMetrics->width( mChr ) / 2.0, -mFontMetrics->ascent() / 2.0 );
1734  mOrigSize = mSize; // save in case the size would be data defined
1735  prepareExpressions( context );
1736 }
1737 
1739 {
1740  Q_UNUSED( context );
1741 }
1742 
1744 {
1745  QPainter *p = context.renderContext().painter();
1746  if ( !p )
1747  return;
1748 
1749  QColor penColor = mColor;
1750  bool ok;
1752  {
1755  if ( ok )
1756  penColor = QgsSymbolLayerV2Utils::decodeColor( colorString );
1757  }
1758  penColor = context.selected() ? context.renderContext().selectionColor() : penColor;
1759  penColor.setAlphaF( penColor.alphaF() * context.alpha() );
1760 
1761  p->setPen( penColor );
1762  p->setFont( mFont );
1763 
1764  p->save();
1765 
1766  QPointF chrOffset = mChrOffset;
1767  QString charToRender = mChr;
1769  {
1770  context.setOriginalValueVariable( mChr );
1772  if ( charToRender != mChr )
1773  {
1774  chrOffset = QPointF( mFontMetrics->width( charToRender ) / 2.0, -mFontMetrics->ascent() / 2.0 );
1775  }
1776  }
1777 
1778  double scaledSize = mSize;
1779 
1781 
1782  ok = true;
1784  {
1785  context.setOriginalValueVariable( mSize );
1786  scaledSize = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_SIZE, context, mSize, &ok ).toDouble();
1787  }
1788 
1789  if ( hasDataDefinedSize && ok )
1790  {
1791  switch ( mScaleMethod )
1792  {
1794  scaledSize = sqrt( scaledSize );
1795  break;
1797  break;
1798  }
1799  }
1800 
1801  //offset
1802  double offsetX = 0;
1803  double offsetY = 0;
1804  markerOffset( context, scaledSize, scaledSize , offsetX, offsetY );
1805  QPointF outputOffset( offsetX, offsetY );
1806 
1807  double angle = mAngle + mLineAngle;
1809  {
1810  context.setOriginalValueVariable( mAngle );
1812  }
1813 
1815  if ( hasDataDefinedRotation )
1816  {
1817  // For non-point markers, "dataDefinedRotation" means following the
1818  // shape (shape-data defined). For them, "field-data defined" does
1819  // not work at all. TODO: if "field-data defined" ever gets implemented
1820  // we'll need a way to distinguish here between the two, possibly
1821  // using another flag in renderHints()
1822  const QgsFeature* f = context.feature();
1823  if ( f )
1824  {
1825  const QgsGeometry *g = f->constGeometry();
1826  if ( g && g->type() == QGis::Point )
1827  {
1828  const QgsMapToPixel& m2p = context.renderContext().mapToPixel();
1829  angle += m2p.mapRotation();
1830  }
1831  }
1832  }
1833 
1834  if ( angle )
1835  outputOffset = _rotatedOffset( outputOffset, angle );
1836  p->translate( point + outputOffset );
1837 
1838  if ( !qgsDoubleNear( scaledSize, mOrigSize ) )
1839  {
1840  double s = scaledSize / mOrigSize;
1841  p->scale( s, s );
1842  }
1843 
1844  bool rotated = !qgsDoubleNear( angle, 0 );
1845  if ( rotated )
1846  p->rotate( angle );
1847 
1848  p->drawText( -chrOffset, charToRender );
1849  p->restore();
1850 }
1851 
1853 {
1854  QgsStringMap props;
1855  props["font"] = mFontFamily;
1856  props["chr"] = mChr;
1857  props["size"] = QString::number( mSize );
1858  props["size_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mSizeUnit );
1859  props["size_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mSizeMapUnitScale );
1860  props["color"] = QgsSymbolLayerV2Utils::encodeColor( mColor );
1861  props["angle"] = QString::number( mAngle );
1862  props["offset"] = QgsSymbolLayerV2Utils::encodePoint( mOffset );
1863  props["offset_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mOffsetUnit );
1864  props["offset_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOffsetMapUnitScale );
1865  props["horizontal_anchor_point"] = QString::number( mHorizontalAnchorPoint );
1866  props["vertical_anchor_point"] = QString::number( mVerticalAnchorPoint );
1867 
1868  //data define properties
1869  saveDataDefinedProperties( props );
1870 
1871  return props;
1872 }
1873 
1875 {
1877  m->setOffset( mOffset );
1878  m->setOffsetUnit( mOffsetUnit );
1880  m->setSizeUnit( mSizeUnit );
1885  copyPaintEffect( m );
1886  return m;
1887 }
1888 
1890 {
1891  // <Graphic>
1892  QDomElement graphicElem = doc.createElement( "se:Graphic" );
1893  element.appendChild( graphicElem );
1894 
1895  QString fontPath = QString( "ttf://%1" ).arg( mFontFamily );
1896  int markIndex = mChr.unicode();
1897  QgsSymbolLayerV2Utils::externalMarkerToSld( doc, graphicElem, fontPath, "ttf", &markIndex, mColor, mSize );
1898 
1899  // <Rotation>
1900  QString angleFunc;
1901  bool ok;
1902  double angle = props.value( "angle", "0" ).toDouble( &ok );
1903  if ( !ok )
1904  {
1905  angleFunc = QString( "%1 + %2" ).arg( props.value( "angle", "0" ) ).arg( mAngle );
1906  }
1907  else if ( angle + mAngle != 0 )
1908  {
1909  angleFunc = QString::number( angle + mAngle );
1910  }
1911  QgsSymbolLayerV2Utils::createRotationElement( doc, graphicElem, angleFunc );
1912 
1913  // <Displacement>
1915 }
1916 
1918 {
1919  QgsDebugMsg( "Entered." );
1920 
1921  QDomElement graphicElem = element.firstChildElement( "Graphic" );
1922  if ( graphicElem.isNull() )
1923  return NULL;
1924 
1925  QString name, format;
1926  QColor color;
1927  double size;
1928  int chr;
1929 
1930  if ( !QgsSymbolLayerV2Utils::externalMarkerFromSld( graphicElem, name, format, chr, color, size ) )
1931  return NULL;
1932 
1933  if ( !name.startsWith( "ttf://" ) || format != "ttf" )
1934  return NULL;
1935 
1936  QString fontFamily = name.mid( 6 );
1937 
1938  double angle = 0.0;
1939  QString angleFunc;
1940  if ( QgsSymbolLayerV2Utils::rotationFromSldElement( graphicElem, angleFunc ) )
1941  {
1942  bool ok;
1943  double d = angleFunc.toDouble( &ok );
1944  if ( ok )
1945  angle = d;
1946  }
1947 
1948  QPointF offset;
1950 
1951  QgsMarkerSymbolLayerV2 *m = new QgsFontMarkerSymbolLayerV2( fontFamily, chr, size, color );
1952  m->setAngle( angle );
1953  m->setOffset( offset );
1954  return m;
1955 }
1956 
1957 
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)
static void createRotationElement(QDomDocument &doc, QDomElement &element, const QString &rotationFunc)
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)
QgsSimpleMarkerSymbolLayerV2(const QString &name=DEFAULT_SIMPLEMARKER_NAME, const QColor &color=DEFAULT_SIMPLEMARKER_COLOR, const QColor &borderColor=DEFAULT_SIMPLEMARKER_BORDERCOLOR, double size=DEFAULT_SIMPLEMARKER_SIZE, double angle=DEFAULT_SIMPLEMARKER_ANGLE, QgsSymbolV2::ScaleMethod scaleMethod=DEFAULT_SCALE_METHOD)
static void multiplyImageOpacity(QImage *image, qreal alpha)
Multiplies opacity of image pixel values with a (global) transparency value.
int ascent() const
OutputUnit
The unit of the output.
Definition: qgssymbolv2.h:55
void writeLine(const QgsPoint &pt1, const QgsPoint &pt2, const QString &layer, const QString &lineStyleName, const QColor &color, double width=-1)
Write line (as a polyline)
int renderHints() const
Definition: qgssymbolv2.h:278
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
static QString encodeColor(const QColor &color)
#define DEFAULT_SIMPLEMARKER_ANGLE
static void externalGraphicToSld(QDomDocument &doc, QDomElement &element, const QString &path, const QString &mime, const QColor &color, double size=-1)
void scale(qreal sx, qreal sy)
#define DEFAULT_FONTMARKER_CHR
bool writeDxf(QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, QgsSymbolV2RenderContext *context, const QgsFeature *f, const QPointF &shift=QPointF(0.0, 0.0)) const override
static QgsSymbolV2::ScaleMethod decodeScaleMethod(const QString &str)
Calculate scale by the diameter.
Definition: qgssymbolv2.h:81
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 setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for data defined symbology.
void writeSldMarker(QDomDocument &doc, QDomElement &element, const QgsStringMap &props) const override
QgsSymbolLayerV2 * clone() const override
void drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
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:76
void moveTo(const QPointF &point)
static QPointF decodePoint(const 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...
void writeSldMarker(QDomDocument &doc, QDomElement &element, const QgsStringMap &props) const override
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:176
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)
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:268
static const QString EXPR_OFFSET
void setMapUnitScale(const QgsMapUnitScale &scale) override
static QgsSymbolLayerV2 * createFromSld(QDomElement &element)
QSize defaultSize() const
#define DEFAULT_SVGMARKER_ANGLE
static const QString EXPR_SIZE
void setOffsetUnit(QgsSymbolV2::OutputUnit unit)
bool isNull() const
#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 QgsSymbolV2::OutputUnit decodeOutputUnit(const QString &str)
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:271
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)
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.
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()
Mixed units in symbol layers.
Definition: qgssymbolv2.h:59
void setFont(const QFont &font)
QTransform & translate(qreal dx, qreal dy)
The output shall be in millimeters.
Definition: qgssymbolv2.h:57
void setMapUnitScale(const QgsMapUnitScale &scale) override
QString number(int n, int base)
void setOutlineWidthUnit(QgsSymbolV2::OutputUnit u)
void markerOffset(QgsSymbolV2RenderContext &context, double &offsetX, double &offsetY) const
qreal x() const
qreal y() const
void resize(int size)
const QgsFeature * feature() const
Current feature being rendered - may be null.
Definition: qgssymbolv2.h:283
QTransform & scale(qreal sx, qreal sy)
void fill(uint pixelValue)
static QString encodePoint(QPointF point)
static double convertToPainterUnits(const QgsRenderContext &c, double size, QgsSymbolV2::OutputUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale())
Converts a size from the specied units to painter units.
QgsStringMap properties() const override
void setPath(const QString &path)
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
void setFillColor(const QColor &color) override
Set fill color.
QgsFontMarkerSymbolLayerV2(const QString &fontFamily=DEFAULT_FONTMARKER_FONT, QChar chr=DEFAULT_FONTMARKER_CHR, double pointSize=DEFAULT_FONTMARKER_SIZE, const QColor &color=DEFAULT_FONTMARKER_COLOR, double angle=DEFAULT_FONTMARKER_ANGLE)
bool prepareShape(const QString &name=QString())
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
void writeFilledCircle(const QString &layer, const QColor &color, const QgsPoint &pt, double radius)
Write filled circle (as hatch)
#define DEFAULT_FONTMARKER_ANGLE
QgsSymbolV2::OutputUnit outputUnit() const override
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.
static QgsSymbolLayerV2 * createFromSld(QDomElement &element)
HorizontalAnchorPoint mHorizontalAnchorPoint
ushort unicode() const
void setColor(const QColor &color)
virtual Q_DECL_DEPRECATED void prepareExpressions(const QgsFields *fields, double scale=-1.0)
Prepares all data defined property expressions for evaluation.
void setOutlineWidthMapUnitScale(const QgsMapUnitScale &scale)
static Qt::PenStyle decodePenStyle(const QString &str)
QgsSymbolV2::ScaleMethod scaleMethod() const
static const QString EXPR_OUTLINE_STYLE
void writePolyline(const QgsPolyline &line, const QString &layer, const QString &lineStyleName, const QColor &color, double width=-1)
Draw dxf primitives (LWPOLYLINE)
bool writeDxf(QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, QgsSymbolV2RenderContext *context, const QgsFeature *f, const QPointF &shift=QPointF(0.0, 0.0)) const override
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 writeCircle(const QString &layer, const QColor &color, const QgsPoint &pt, double radius, const QString &lineStyleName, double width)
Write circle (as polyline)
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 Q_DECL_DEPRECATED 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
ScaleMethod
Scale method.
Definition: qgssymbolv2.h:78
Struct for storing maximum and minimum scales for measurements in map units.
QgsMapUnitScale mapUnitScale() const override
Qt::PenStyle outlineStyle() const
static const QString EXPR_NAME
QgsSvgMarkerSymbolLayerV2(const QString &name=DEFAULT_SVGMARKER_NAME, double size=DEFAULT_SVGMARKER_SIZE, double angle=DEFAULT_SVGMARKER_ANGLE, QgsSymbolV2::ScaleMethod scaleMethod=DEFAULT_SCALE_METHOD)
void setShift(const QPointF &shift)
bool isEmpty() const
void writeSldMarker(QDomDocument &doc, QDomElement &element, const QgsStringMap &props) const override
static QString encodeScaleMethod(QgsSymbolV2::ScaleMethod scaleMethod)
QgsRenderContext & renderContext()
Definition: qgssymbolv2.h:254
QDomElement firstChildElement(const QString &tagName) const
bool preparePath(QString name=QString())
int height() const
int count(const T &value) const
static const QString EXPR_COLOR_BORDER
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
Definition: qgsfeature.cpp:70
void writePolygon(const QgsPolygon &polygon, const QString &layer, const QString &hatchPattern, const QColor &color)
Draw dxf polygon (HATCH)
qreal widthF() const
void translate(const QPointF &offset)
const QgsMapToPixel & mapToPixel() const
QgsSymbolV2::OutputUnit mOffsetUnit
void setAlphaF(qreal alpha)
virtual void setColor(const QColor &color)
void startRender(QgsSymbolV2RenderContext &context) override
static bool rotationFromSldElement(QDomElement &element, QString &rotationFunc)
bool selected() const
Definition: qgssymbolv2.h:275
int height() const
double toDouble(bool *ok) const
static QColor decodeColor(const QString &str)
void startRender(QgsSymbolV2RenderContext &context) override
VerticalAnchorPoint mVerticalAnchorPoint
QgsSymbolV2::OutputUnit mSizeUnit
Calculate scale by the area.
Definition: qgssymbolv2.h:80
void setDrawingSize(const QSizeF &size)
QgsMapUnitScale mOffsetMapUnitScale
void drawPicture(const QPointF &point, const QPicture &picture)
static const QString EXPR_OUTLINE
void restoreDataDefinedProperties(const QgsStringMap &stringMap)
Restores all data defined properties from string map.
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
int height() const
QDomElement createElement(const QString &tagName)
static void externalMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &path, const QString &format, int *markIndex=0, const QColor &color=QColor(), double size=-1)
void map(int x, int y, int *tx, int *ty) const
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.
void renderPoint(const QPointF &point, QgsSymbolV2RenderContext &context) override
void copyDataDefinedProperties(QgsSymbolLayerV2 *destLayer) const
Copies all data defined properties of this layer to another symbol layer.
QMatrix & scale(qreal sx, qreal sy)
void setOutputSize(const QRectF &r)
const T value(const Key &key) const
static Q_DECL_DEPRECATED void wellKnownMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &name, const QColor &color, const QColor &borderColor=QColor(), double borderWidth=-1, double size=-1)
static QPointF _rotatedOffset(const QPointF &offset, double angle)
#define DEFAULT_SIMPLEMARKER_BORDERCOLOR