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 );