25 #include <QSvgRenderer>
28 #include <QDomDocument>
29 #include <QDomElement>
36 : mOutlineWidth( 0 ), mOutlineWidthUnit(
QgsSymbolV2::MM )
58 if ( props.contains(
"name" ) )
60 if ( props.contains(
"color" ) )
62 if ( props.contains(
"color_border" ) )
64 if ( props.contains(
"size" ) )
65 size = props[
"size"].toDouble();
66 if ( props.contains(
"angle" ) )
67 angle = props[
"angle"].toDouble();
68 if ( props.contains(
"scale_method" ) )
72 if ( props.contains(
"offset" ) )
74 if ( props.contains(
"offset_unit" ) )
76 if ( props.contains(
"size_unit" ) )
79 if ( props.contains(
"outline_width" ) )
83 if ( props.contains(
"outline_width_unit" ) )
89 if ( props.contains(
"name_expression" ) )
93 if ( props.contains(
"color_expression" ) )
97 if ( props.contains(
"color_border_expression" ) )
101 if ( props.contains(
"outline_width_expression" ) )
105 if ( props.contains(
"size_expression" ) )
109 if ( props.contains(
"angle_expression" ) )
113 if ( props.contains(
"offset_expression" ) )
123 return "SimpleMarker";
128 QColor brushColor =
mColor;
131 brushColor.setAlphaF(
mColor.alphaF() * context.
alpha() );
134 mBrush = QBrush( brushColor );
135 mPen = QPen( penColor );
140 if ( context.
alpha() < 1 )
142 selBrushColor.setAlphaF( context.
alpha() );
143 selPenColor.setAlphaF( context.
alpha() );
168 if (
mName !=
"circle" )
169 mSelPen.setColor( selBrushColor );
181 if ( !hasDataDefinedSize )
186 double half = scaledSize / 2.0;
187 transform.scale( half, half );
191 if ( !hasDataDefinedRotation &&
mAngle != 0 )
193 transform.rotate(
mAngle );
223 double pw = ((
mPen.widthF() == 0 ? 1 :
mPen.widthF() ) + 1 ) / 2 * 2;
224 int imageSize = (( int ) scaledSize + pw ) / 2 * 2 + 1;
225 double center = imageSize / 2.0;
232 mCache = QImage( QSize( imageSize, imageSize ), QImage::Format_ARGB32_Premultiplied );
237 p.setRenderHint( QPainter::Antialiasing );
240 p.translate( QPointF( center, center ) );
248 mSelCache = QImage( QSize( imageSize, imageSize ), QImage::Format_ARGB32_Premultiplied );
252 p.setRenderHint( QPainter::Antialiasing );
255 p.translate( QPointF( center, center ) );
266 p.setRenderHint( QPainter::Antialiasing );
267 p.fillRect( 0, 0, imageSize, imageSize, selColor );
270 p.translate( QPointF( center, center ) );
292 if ( name ==
"square" || name ==
"rectangle" )
294 mPolygon = QPolygonF( QRectF( QPointF( -1, -1 ), QPointF( 1, 1 ) ) );
297 else if ( name ==
"diamond" )
299 mPolygon << QPointF( -1, 0 ) << QPointF( 0, 1 )
300 << QPointF( 1, 0 ) << QPointF( 0, -1 );
303 else if ( name ==
"pentagon" )
312 else if ( name ==
"triangle" )
314 mPolygon << QPointF( -1, 1 ) << QPointF( 1, 1 ) << QPointF( 0, -1 );
317 else if ( name ==
"equilateral_triangle" )
324 else if ( name ==
"star" )
326 double sixth = 1.0 / 3;
329 << QPointF( -sixth, -sixth )
330 << QPointF( -1, -sixth )
331 << QPointF( -sixth, 0 )
333 << QPointF( 0, + sixth )
335 << QPointF( + sixth, 0 )
336 << QPointF( 1, -sixth )
337 << QPointF( + sixth, -sixth );
340 else if ( name ==
"regular_star" )
346 << QPointF( inner_r * sin(
DEG2RAD( 252.0 ) ), - inner_r * cos(
DEG2RAD( 252.0 ) ) )
348 << QPointF( 0, inner_r )
350 << QPointF( inner_r * sin(
DEG2RAD( 108.0 ) ), - inner_r * cos(
DEG2RAD( 108.0 ) ) )
352 << QPointF( inner_r * sin(
DEG2RAD( 36.0 ) ), - inner_r * cos(
DEG2RAD( 36.0 ) ) )
356 else if ( name ==
"arrow" )
360 << QPointF( 0.5, -0.5 )
361 << QPointF( 0.25, -0.25 )
362 << QPointF( 0.25, 1 )
363 << QPointF( -0.25, 1 )
364 << QPointF( -0.25, -0.5 )
365 << QPointF( -0.5, -0.5 );
368 else if ( name ==
"filled_arrowhead" )
370 mPolygon << QPointF( 0, 0 ) << QPointF( -1, 1 ) << QPointF( -1, -1 );
379 mPath = QPainterPath();
385 if ( name ==
"circle" )
387 mPath.addEllipse( QRectF( -1, -1, 2, 2 ) );
390 else if ( name ==
"cross" )
392 mPath.moveTo( -1, 0 );
393 mPath.lineTo( 1, 0 );
394 mPath.moveTo( 0, -1 );
395 mPath.lineTo( 0, 1 );
398 else if ( name ==
"x" || name ==
"cross2" )
400 mPath.moveTo( -1, -1 );
401 mPath.lineTo( 1, 1 );
402 mPath.moveTo( 1, -1 );
403 mPath.lineTo( -1, 1 );
406 else if ( name ==
"line" )
408 mPath.moveTo( 0, -1 );
409 mPath.lineTo( 0, 1 );
412 else if ( name ==
"arrowhead" )
414 mPath.moveTo( 0, 0 );
415 mPath.lineTo( -1, -1 );
416 mPath.moveTo( 0, 0 );
417 mPath.lineTo( -1, 1 );
436 QPointF off( offsetX, offsetY );
441 if ( angleExpression )
443 angle = angleExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
450 if ( nameExpression )
452 QString
name = nameExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toString();
464 p->drawImage( QRectF( point.x() - s / 2.0 + off.x(),
465 point.y() - s / 2.0 + off.y(),
473 transform.translate( point.x() + off.x(), point.y() + off.y() );
479 if ( hasDataDefinedSize )
481 double scaledSize =
mSize;
482 if ( sizeExpression )
484 scaledSize = sizeExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
491 scaledSize = sqrt( scaledSize );
497 double half = scaledSize / 2.0;
498 transform.scale( half, half );
502 if ( angle != 0 && hasDataDefinedRotation )
503 transform.rotate( angle );
508 if ( colorExpression )
512 if ( colorBorderExpression )
517 if ( outlineWidthExpression )
528 p->drawPolygon( transform.map(
mPolygon ) );
530 p->drawPath( transform.map(
mPath ) );
541 map[
"size"] = QString::number(
mSize );
543 map[
"angle"] = QString::number(
mAngle );
570 QDomElement graphicElem = doc.createElement(
"se:Graphic" );
571 element.appendChild( graphicElem );
578 double angle = props.value(
"angle",
"0" ).toDouble( &ok );
581 angleFunc = QString(
"%1 + %2" ).arg( props.value(
"angle",
"0" ) ).arg(
mAngle );
583 else if ( angle +
mAngle != 0 )
585 angleFunc = QString::number( angle +
mAngle );
595 Q_UNUSED( mmScaleFactor );
596 Q_UNUSED( mapUnitScaleFactor );
598 QString ogrType =
"3";
599 if (
mName ==
"square" )
603 else if (
mName ==
"triangle" )
607 else if (
mName ==
"star" )
611 else if (
mName ==
"circle" )
615 else if (
mName ==
"cross" )
623 else if (
mName ==
"line" )
629 ogrString.append(
"SYMBOL(" );
630 ogrString.append(
"id:" );
631 ogrString.append(
"\"" );
632 ogrString.append(
"ogr-sym-" );
633 ogrString.append( ogrType );
634 ogrString.append(
"\"" );
635 ogrString.append(
",c:" );
636 ogrString.append(
mColor.name() );
637 ogrString.append(
",o:" );
639 ogrString.append( QString(
",s:%1mm" ).arg(
mSize ) );
640 ogrString.append(
")" );
645 ogrString.append(
"PEN(" );
646 ogrString.append(
"c:" );
647 ogrString.append(
mColor.name() );
648 ogrString.append(
",w:" );
649 ogrString.append( QString::number(
mSize ) );
650 ogrString.append(
"mm" );
651 ogrString.append(
")" );
659 QDomElement graphicElem = element.firstChildElement(
"Graphic" );
660 if ( graphicElem.isNull() )
663 QString
name =
"square";
665 double borderWidth,
size;
675 double d = angleFunc.toDouble( &ok );
699 p->drawPath(
mPath );
725 if ( props.contains(
"name" ) )
726 name = props[
"name"];
727 if ( props.contains(
"size" ) )
728 size = props[
"size"].toDouble();
729 if ( props.contains(
"angle" ) )
730 angle = props[
"angle"].toDouble();
735 if ( !props.contains(
"fill" ) && !props.contains(
"outline" ) && !props.contains(
"outline-width" ) )
739 bool hasFillParam, hasOutlineParam, hasOutlineWidthParam;
745 if ( hasOutlineParam )
749 if ( hasOutlineWidthParam )
755 if ( props.contains(
"size_unit" ) )
757 if ( props.contains(
"offset" ) )
759 if ( props.contains(
"offset_unit" ) )
761 if ( props.contains(
"fill" ) )
763 if ( props.contains(
"outline" ) )
765 if ( props.contains(
"outline-width" ) )
767 if ( props.contains(
"outline_width_unit" ) )
771 if ( props.contains(
"size_expression" ) )
775 if ( props.contains(
"outline-width_expression" ) )
779 if ( props.contains(
"angle_expression" ) )
783 if ( props.contains(
"offset_expression" ) )
787 if ( props.contains(
"name_expression" ) )
791 if ( props.contains(
"fill_expression" ) )
795 if ( props.contains(
"outline_expression" ) )
807 bool hasFillParam, hasOutlineParam, hasOutlineWidthParam;
813 if ( hasOutlineParam )
817 if ( hasOutlineWidthParam )
851 if ( sizeExpression )
853 size = sizeExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
857 if ( hasDataDefinedSize )
870 if ((
int )size < 1 || 10000.0 < size )
879 if ( offsetExpression )
881 QString offsetString = offsetExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toString();
886 QPointF outputOffset( offsetX, offsetY );
890 if ( angleExpression )
892 angle = angleExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
896 p->translate( point + outputOffset );
905 if ( nameExpression )
907 path = nameExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toString();
912 if ( outlineWidthExpression )
914 outlineWidth = outlineWidthExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
919 if ( fillExpression )
926 if ( outlineExpression )
932 bool fitsInCache =
true;
934 double hwRatio = 1.0;
935 if ( drawOnScreen && !rotated )
940 if ( fitsInCache && img.width() > 1 )
945 QImage transparentImage = img.copy();
947 p->drawImage( -transparentImage.width() / 2.0, -transparentImage.height() / 2.0, transparentImage );
948 hwRatio = ( double )transparentImage.height() / ( double )transparentImage.width();
952 p->drawImage( -img.width() / 2.0, -img.height() / 2.0, img );
953 hwRatio = ( double )img.height() / ( double )img.width();
958 if ( usePict || !fitsInCache )
960 p->setOpacity( context.
alpha() );
964 if ( pct.width() > 1 )
966 p->drawPicture( 0, 0, pct );
967 hwRatio = ( double )pct.height() / ( double )pct.width();
975 if ( penWidth > size / 20 )
978 penWidth = size / 20;
980 double penOffset = penWidth / 2;
981 pen.setWidth( penWidth );
983 p->setBrush( Qt::NoBrush );
984 double wSize = size + penOffset;
985 double hSize = size * hwRatio + penOffset;
986 p->drawRect( QRectF( -wSize / 2.0, -hSize / 2.0, wSize, hSize ) );
997 map[
"size"] = QString::number(
mSize );
999 map[
"angle"] = QString::number(
mAngle );
1044 QDomElement graphicElem = doc.createElement(
"se:Graphic" );
1045 element.appendChild( graphicElem );
1052 double angle = props.value(
"angle",
"0" ).toDouble( &ok );
1055 angleFunc = QString(
"%1 + %2" ).arg( props.value(
"angle",
"0" ) ).arg(
mAngle );
1057 else if ( angle +
mAngle != 0 )
1059 angleFunc = QString::number( angle +
mAngle );
1072 QDomElement graphicElem = element.firstChildElement(
"Graphic" );
1073 if ( graphicElem.isNull() )
1076 QString
path, mimeType;
1083 if ( mimeType !=
"image/svg+xml" )
1091 double d = angleFunc.toDouble( &ok );
1130 if ( props.contains(
"font" ) )
1131 fontFamily = props[
"font"];
1132 if ( props.contains(
"chr" ) && props[
"chr"].length() > 0 )
1133 chr = props[
"chr"].at( 0 );
1134 if ( props.contains(
"size" ) )
1135 pointSize = props[
"size"].toDouble();
1136 if ( props.contains(
"color" ) )
1138 if ( props.contains(
"angle" ) )
1139 angle = props[
"angle"].toDouble();
1142 if ( props.contains(
"offset" ) )
1144 if ( props.contains(
"offset_unit" ) )
1146 if ( props.contains(
"size_unit" ) )
1153 return "FontMarker";
1160 QFontMetrics fm(
mFont );
1168 Q_UNUSED( context );
1178 penColor.setAlphaF(
mColor.alphaF() * context.
alpha() );
1179 p->setPen( penColor );
1180 p->setFont(
mFont );
1185 QPointF outputOffset( offsetX, offsetY );
1188 p->translate( point + outputOffset );
1207 props[
"chr"] =
mChr;
1208 props[
"size"] = QString::number(
mSize );
1211 props[
"angle"] = QString::number(
mAngle );
1229 QDomElement graphicElem = doc.createElement(
"se:Graphic" );
1230 element.appendChild( graphicElem );
1232 QString fontPath = QString(
"ttf://%1" ).arg(
mFontFamily );
1233 int markIndex =
mChr.unicode();
1239 double angle = props.value(
"angle",
"0" ).toDouble( &ok );
1242 angleFunc = QString(
"%1 + %2" ).arg( props.value(
"angle",
"0" ) ).arg(
mAngle );
1244 else if ( angle +
mAngle != 0 )
1246 angleFunc = QString::number( angle +
mAngle );
1258 QDomElement graphicElem = element.firstChildElement(
"Graphic" );
1259 if ( graphicElem.isNull() )
1262 QString name, format;
1270 if ( !name.startsWith(
"ttf://" ) || format !=
"ttf" )
1280 double d = angleFunc.toDouble( &ok );
QString ogrFeatureStyle(double mmScaleFactor, double mapUnitScaleFactor) const
QColor borderColor() const
static QString encodeOutputUnit(QgsSymbolV2::OutputUnit unit)
Class for parsing and evaluation of expressions (formerly called "search strings").
QgsSymbolLayerV2 * clone() const
double outlineWidth() const
static void multiplyImageOpacity(QImage *image, qreal alpha)
Multiplies opacity of image pixel values with a (global) transparency value.
void markerOffset(QgsSymbolV2RenderContext &context, double &offsetX, double &offsetY)
static bool wellKnownMarkerFromSld(QDomElement &element, QString &name, QColor &color, QColor &borderColor, double &borderWidth, double &size)
void startRender(QgsSymbolV2RenderContext &context)
#define DEFAULT_FONTMARKER_COLOR
const QPicture & svgAsPicture(const QString &file, double size, const QColor &fill, const QColor &outline, double outlineWidth, double widthScaleFactor, double rasterScaleFactor, bool forceVectorOutput=false)
QVariant evaluate(const QgsFeature *f=NULL)
Evaluate the feature and return the result.
QColor selectionColor() const
Added in QGIS v2.0.
QgsSymbolV2::OutputUnit mOutlineWidthUnit
#define DEFAULT_SIMPLEMARKER_ANGLE
void renderPoint(const QPointF &point, QgsSymbolV2RenderContext &context)
QString layerType() const
void writeSldMarker(QDomDocument &doc, QDomElement &element, QgsStringMap props) const
void setFillColor(const QColor &c)
static void createRotationElement(QDomDocument &doc, QDomElement &element, QString rotationFunc)
void stopRender(QgsSymbolV2RenderContext &context)
#define DEFAULT_FONTMARKER_CHR
void setOffset(QPointF offset)
void setOutlineWidth(double w)
#define DEFAULT_SIMPLEMARKER_COLOR
static QPointF decodePoint(QString str)
static bool externalGraphicFromSld(QDomElement &element, QString &path, QString &mime, QColor &color, double &size)
static QColor decodeColor(QString str)
void setOutlineWidth(double w)
double scaleFactor() const
void writeSldMarker(QDomDocument &doc, QDomElement &element, QgsStringMap props) const
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
static void createDisplacementElement(QDomDocument &doc, QDomElement &element, QPointF offset)
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
QMap< QString, QString > QgsStringMap
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
static QgsSymbolLayerV2 * createFromSld(QDomElement &element)
#define DEFAULT_SVGMARKER_ANGLE
void setOffsetUnit(QgsSymbolV2::OutputUnit unit)
void startRender(QgsSymbolV2RenderContext &context)
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)
QgsSvgMarkerSymbolLayerV2(QString name=DEFAULT_SVGMARKER_NAME, double size=DEFAULT_SVGMARKER_SIZE, double angle=DEFAULT_SVGMARKER_ANGLE)
qreal alpha() const
Get alpha transparency 1 for opaque, 0 for invisible.
void drawMarker(QPainter *p, QgsSymbolV2RenderContext &context)
static QgsSvgCache * instance()
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)
QgsFontMarkerSymbolLayerV2(QString fontFamily=DEFAULT_FONTMARKER_FONT, QChar chr=DEFAULT_FONTMARKER_CHR, double pointSize=DEFAULT_FONTMARKER_SIZE, QColor color=DEFAULT_FONTMARKER_COLOR, double angle=DEFAULT_FONTMARKER_ANGLE)
static QString symbolPathToName(QString path)
Get symbols's name from its path.
void setOutlineWidthUnit(QgsSymbolV2::OutputUnit u)
void setOutputUnit(QgsSymbolV2::OutputUnit unit)
const QgsFeature * feature() const
static QString encodePoint(QPointF point)
virtual void prepareExpressions(const QgsVectorLayer *vl)
#define DEFAULT_SCALE_METHOD
QString fontFamily() const
double outlineWidth() const
QgsSymbolV2::ScaleMethod mScaleMethod
static QString symbolNameToPath(QString name)
Get symbol's path from its name.
bool forceVectorOutput() const
void setSizeUnit(QgsSymbolV2::OutputUnit unit)
static bool externalMarkerFromSld(QDomElement &element, QString &path, QString &format, int &markIndex, QColor &color, double &size)
void startRender(QgsSymbolV2RenderContext &context)
void setPath(QString path)
double rasterScaleFactor() const
#define DEFAULT_FONTMARKER_ANGLE
virtual QColor color() const
QgsStringMap properties() const
static QgsSymbolLayerV2 * createFromSld(QDomElement &element)
QgsSymbolV2::ScaleMethod scaleMethod() const
QgsSymbolV2::OutputUnit mOutlineWidthUnit
#define DEFAULT_SVGMARKER_SIZE
double ANALYSIS_EXPORT angle(Point3D *p1, Point3D *p2, Point3D *p3, Point3D *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
QgsSymbolLayerV2 * clone() const
QString layerType() const
void renderPoint(const QPointF &point, QgsSymbolV2RenderContext &context)
void writeSldMarker(QDomDocument &doc, QDomElement &element, QgsStringMap props) const
QColor outlineColor() const
#define DEFAULT_FONTMARKER_SIZE
#define DEFAULT_FONTMARKER_FONT
QString layerType() const
#define DEFAULT_SVGMARKER_NAME
#define DEFAULT_SIMPLEMARKER_SIZE
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
void stopRender(QgsSymbolV2RenderContext &context)
QgsSimpleMarkerSymbolLayerV2(QString name=DEFAULT_SIMPLEMARKER_NAME, QColor color=DEFAULT_SIMPLEMARKER_COLOR, QColor borderColor=DEFAULT_SIMPLEMARKER_BORDERCOLOR, double size=DEFAULT_SIMPLEMARKER_SIZE, double angle=DEFAULT_SIMPLEMARKER_ANGLE, QgsSymbolV2::ScaleMethod scaleMethod=DEFAULT_SCALE_METHOD)
virtual const QgsExpression * dataDefinedProperty(const QString &property) const
static QString encodeScaleMethod(QgsSymbolV2::ScaleMethod scaleMethod)
QgsRenderContext & renderContext()
bool preparePath(QString name=QString())
QgsStringMap properties() const
static void externalGraphicToSld(QDomDocument &doc, QDomElement &element, QString path, QString mime, QColor color, double size=-1)
static double lineWidthScaleFactor(const QgsRenderContext &c, QgsSymbolV2::OutputUnit u)
Returns the line width scale factor depending on the unit and the paint device.
static void wellKnownMarkerToSld(QDomDocument &doc, QDomElement &element, QString name, QColor color, QColor borderColor=QColor(), double borderWidth=-1, double size=-1)
QgsStringMap properties() const
QgsSymbolV2::OutputUnit mOffsetUnit
static bool rotationFromSldElement(QDomElement &element, QString &rotationFunc)
QgsSymbolLayerV2 * clone() const
QgsSymbolV2::OutputUnit outputUnit() const
static QgsSymbolV2::ScaleMethod decodeScaleMethod(QString str)
bool prepareShape(QString name=QString())
QgsSymbolV2::OutputUnit mSizeUnit
void setOutlineColor(const QColor &c)
void stopRender(QgsSymbolV2RenderContext &context)
void setAngle(double angle)
static QgsSymbolLayerV2 * createFromSld(QDomElement &element)
void saveDataDefinedProperties(QgsStringMap &stringMap) const
Saves data defined properties to string map.
virtual QgsExpression * expression(const QString &property)
bool prepareCache(QgsSymbolV2RenderContext &context)
Prepares cache image.
static QgsSymbolV2::OutputUnit decodeOutputUnit(QString str)
static void externalMarkerToSld(QDomDocument &doc, QDomElement &element, QString path, QString format, int *markIndex=0, QColor color=QColor(), double size=-1)
static const int mMaximumCacheWidth
void copyDataDefinedProperties(QgsSymbolLayerV2 *destLayer) const
Copies data defined properties of this layer to another symbol layer.
void renderPoint(const QPointF &point, QgsSymbolV2RenderContext &context)
const QgsVectorLayer * layer() const
virtual void setDataDefinedProperty(const QString &property, const QString &expressionString)
static QPointF _rotatedOffset(const QPointF &offset, double angle)
#define DEFAULT_SIMPLEMARKER_BORDERCOLOR