27 #include <QSvgRenderer>
28 #include <QDomDocument>
29 #include <QDomElement>
32 : mBrushStyle( style ), mBorderColor( borderColor ), mBorderStyle( borderStyle ), mBorderWidth( borderWidth ), mBorderWidthUnit(
QgsSymbolV2::MM ),
57 if ( colorExpression )
62 if ( colorBorderExpression )
67 if ( widthBorderExpression )
69 double width = widthBorderExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
71 pen.setWidthF( width );
72 selPen.setWidthF( width );
86 if ( props.contains(
"color" ) )
88 if ( props.contains(
"style" ) )
90 if ( props.contains(
"color_border" ) )
92 if ( props.contains(
"style_border" ) )
94 if ( props.contains(
"width_border" ) )
95 borderWidth = props[
"width_border"].toDouble();
96 if ( props.contains(
"offset" ) )
101 if ( props.contains(
"border_width_unit" ) )
103 if ( props.contains(
"offset_unit" ) )
106 if ( props.contains(
"color_expression" ) )
110 if ( props.contains(
"color_border_expression" ) )
114 if ( props.contains(
"width_border_expression" ) )
129 QColor fillColor =
mColor;
130 fillColor.setAlphaF( context.
alpha() *
mColor.alphaF() );
135 if ( rasterScaleFactor != 1.0 )
137 mBrush.setMatrix( QMatrix().scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor ) );
151 mPen = QPen( borderColor );
182 p->translate( offset );
189 p->translate( -offset );
223 QDomElement symbolizerElem = doc.createElement(
"se:PolygonSymbolizer" );
224 if ( !props.value(
"uom",
"" ).isEmpty() )
225 symbolizerElem.setAttribute(
"uom", props.value(
"uom",
"" ) );
226 element.appendChild( symbolizerElem );
234 QDomElement fillElem = doc.createElement(
"se:Fill" );
235 symbolizerElem.appendChild( fillElem );
242 QDomElement strokeElem = doc.createElement(
"se:Stroke" );
243 symbolizerElem.appendChild( strokeElem );
256 symbolStyle.append(
";" );
267 Qt::BrushStyle fillStyle;
271 QDomElement fillElem = element.firstChildElement(
"Fill" );
274 QDomElement strokeElem = element.firstChildElement(
"Stroke" );
308 p->setPen( QPen( Qt::NoPen ) );
315 p->setBrush( QBrush( selColor ) );
325 QTransform t =
mBrush.transform();
327 QBrush rotatedBrush =
mBrush;
328 rotatedBrush.setTransform( t );
329 p->setBrush( rotatedBrush );
337 QList<QPolygonF>::const_iterator ringIt = rings->constBegin();
338 for ( ; ringIt != rings->constEnd(); ++ringIt )
435 if ( properties.contains(
"width" ) )
437 width = properties[
"width"].toDouble();
439 if ( properties.contains(
"svgFile" ) )
441 QString svgName = properties[
"svgFile"];
443 svgFilePath = ( savePath.isEmpty() ? svgName : savePath );
445 if ( properties.contains(
"angle" ) )
447 angle = properties[
"angle"].toDouble();
451 if ( !svgFilePath.isEmpty() )
457 if ( properties.contains(
"data" ) )
459 data = QByteArray::fromHex( properties[
"data"].toLocal8Bit() );
465 if ( properties.contains(
"svgFillColor" ) )
469 if ( properties.contains(
"svgOutlineColor" ) )
473 if ( properties.contains(
"svgOutlineWidth" ) )
479 if ( properties.contains(
"pattern_width_unit" ) )
483 if ( properties.contains(
"svg_outline_width_unit" ) )
487 if ( properties.contains(
"outline_width_unit" ) )
492 if ( properties.contains(
"width_expression" ) )
494 if ( properties.contains(
"svgFile_expression" ) )
496 if ( properties.contains(
"angle_expression" ) )
498 if ( properties.contains(
"svgFillColor_expression" ) )
500 if ( properties.contains(
"svgOutlineColor_expression" ) )
502 if ( properties.contains(
"svgOutlineWidth" ) )
514 const QColor& svgFillColor,
const QColor& svgOutlineColor,
double svgOutlineWidth,
526 if ((
int )size < 1.0 || 10000.0 <
size )
533 bool fitsInCache =
true;
541 double hwRatio = 1.0;
542 if ( patternPict.width() > 0 )
544 hwRatio = ( double )patternPict.height() / ( double )patternPict.width();
546 mSvgPattern =
new QImage((
int )size, (
int )( size * hwRatio ), QImage::Format_ARGB32_Premultiplied );
550 p.drawPicture( QPointF( size / 2, size * hwRatio / 2 ), patternPict );
553 QTransform brushTransform;
557 QImage transparentImage = fitsInCache ? patternImage.copy() :
mSvgPattern->copy();
559 brush.setTextureImage( transparentImage );
563 brush.setTextureImage( fitsInCache ? patternImage : *
mSvgPattern );
565 brush.setTransform( brushTransform );
599 map.insert(
"data", QString(
mSvgData.toHex() ) );
603 map.insert(
"angle", QString::number(
mAngle ) );
648 QDomElement symbolizerElem = doc.createElement(
"se:PolygonSymbolizer" );
649 if ( !props.value(
"uom",
"" ).isEmpty() )
650 symbolizerElem.setAttribute(
"uom", props.value(
"uom",
"" ) );
651 element.appendChild( symbolizerElem );
655 QDomElement fillElem = doc.createElement(
"se:Fill" );
656 symbolizerElem.appendChild( fillElem );
658 QDomElement graphicFillElem = doc.createElement(
"se:GraphicFill" );
659 fillElem.appendChild( graphicFillElem );
661 QDomElement graphicElem = doc.createElement(
"se:Graphic" );
662 graphicFillElem.appendChild( graphicElem );
672 symbolizerElem.appendChild( doc.createComment(
"SVG from data not implemented yet" ) );
683 double angle = props.value(
"angle",
"0" ).toDouble( &ok );
686 angleFunc = QString(
"%1 + %2" ).arg( props.value(
"angle",
"0" ) ).arg(
mAngle );
688 else if ( angle +
mAngle != 0 )
690 angleFunc = QString::number( angle +
mAngle );
707 QString path, mimeType;
708 QColor fillColor, borderColor;
709 Qt::PenStyle penStyle;
710 double size, borderWidth;
712 QDomElement fillElem = element.firstChildElement(
"Fill" );
713 if ( fillElem.isNull() )
716 QDomElement graphicFillElem = fillElem.firstChildElement(
"GraphicFill" );
717 if ( graphicFillElem.isNull() )
720 QDomElement graphicElem = graphicFillElem.firstChildElement(
"Graphic" );
721 if ( graphicElem.isNull() )
727 if ( mimeType !=
"image/svg+xml" )
737 double d = angleFunc.toDouble( &ok );
748 QDomElement strokeElem = element.firstChildElement(
"Stroke" );
749 if ( !strokeElem.isNull() )
771 if ( !widthExpression && !svgFileExpression && !fillColorExpression && !outlineColorExpression && !outlineWidthExpression && !angleExpression )
776 if ( angleExpression )
782 if ( widthExpression )
784 width = widthExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
787 if ( svgFileExpression )
789 svgFile = svgFileExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toString();
792 if ( fillColorExpression )
797 if ( outlineColorExpression )
802 if ( outlineWidthExpression )
804 outlineWidth = outlineWidthExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
839 bool hasFillParam, hasOutlineParam, hasOutlineWidthParam;
840 QColor defaultFillColor, defaultOutlineColor;
841 double defaultOutlineWidth;
843 defaultOutlineWidth );
849 if ( hasOutlineParam )
853 if ( hasOutlineWidthParam )
893 QColor
color( Qt::black );
896 if ( properties.contains(
"lineangle" ) )
898 lineAngle = properties[
"lineangle"].toDouble();
902 if ( properties.contains(
"distance" ) )
904 distance = properties[
"distance"].toDouble();
908 if ( properties.contains(
"linewidth" ) )
910 lineWidth = properties[
"linewidth"].toDouble();
914 if ( properties.contains(
"color" ) )
920 if ( properties.contains(
"offset" ) )
922 offset = properties[
"offset"].toDouble();
927 if ( properties.contains(
"distance_unit" ) )
931 if ( properties.contains(
"line_width_unit" ) )
935 if ( properties.contains(
"offset_unit" ) )
941 if ( properties.contains(
"lineangle_expression" ) )
945 if ( properties.contains(
"distance_expression" ) )
949 if ( properties.contains(
"linewidth_expression" ) )
953 if ( properties.contains(
"color_expression" ) )
962 return "LinePatternFill";
966 double lineWidth,
const QColor& color )
970 double outputPixelDist = distance * QgsSymbolLayerV2Utils::pixelSizeScaleFactor( ctx,
mDistanceUnit );
971 double outputPixelOffset =
mOffset * QgsSymbolLayerV2Utils::pixelSizeScaleFactor( ctx,
mOffsetUnit );
977 height = outputPixelDist;
982 height = qAbs( outputPixelDist / cos( lineAngle *
M_PI / 180 ) );
983 width = qAbs( height / tan( lineAngle *
M_PI / 180 ) );
990 if ( width > 10000 || height > 10000 )
993 mBrush.setTextureImage( img );
997 QImage patternImage( width, height, QImage::Format_ARGB32 );
998 patternImage.fill( 0 );
999 QPainter p( &patternImage );
1001 p.setRenderHint( QPainter::Antialiasing,
true );
1003 pen.setWidthF( outlinePixelWidth );
1004 pen.setCapStyle( Qt::FlatCap );
1007 QPoint p1, p2, p3, p4, p5, p6;
1010 p1 = QPoint( 0, height );
1011 p2 = QPoint( width, height );
1012 p3 = QPoint( 0, 0 );
1013 p4 = QPoint( width, 0 );
1014 p5 = QPoint( 0, 2 * height );
1015 p6 = QPoint( width, 2 * height );
1019 p1 = QPoint( 0, height );
1020 p2 = QPoint( 0, 0 );
1021 p3 = QPoint( width, height );
1022 p4 = QPoint( width, 0 );
1023 p5 = QPoint( -width, height );
1024 p6 = QPoint( -width, 0 );
1026 else if (( lineAngle > 0 && lineAngle < 90 ) || ( lineAngle > 180 && lineAngle < 270 ) )
1028 dx = outputPixelDist * cos(( 90 - lineAngle ) *
M_PI / 180.0 );
1029 dy = outputPixelDist * sin(( 90 - lineAngle ) *
M_PI / 180.0 );
1030 p1 = QPoint( 0, height );
1031 p2 = QPoint( width, 0 );
1032 p3 = QPoint( -dx, height - dy );
1033 p4 = QPoint( width - dx, -dy );
1034 p5 = QPoint( dx, height + dy );
1035 p6 = QPoint( width + dx, dy );
1037 else if (( lineAngle < 180 ) || ( lineAngle > 270 && lineAngle < 360 ) )
1039 dy = outputPixelDist * cos(( 180 - lineAngle ) *
M_PI / 180 );
1040 dx = outputPixelDist * sin(( 180 - lineAngle ) *
M_PI / 180 );
1041 p1 = QPoint( width, height );
1042 p2 = QPoint( 0, 0 );
1043 p5 = QPoint( width + dx, height - dy );
1044 p6 = QPoint( p5.x() - width, p5.y() - height );
1045 p3 = QPoint( width - dx, height + dy );
1046 p4 = QPoint( p3.x() - width, p3.y() - height );
1053 p3 = QPoint( tempPt.x(), tempPt.y() );
1055 p4 = QPoint( tempPt.x(), tempPt.y() );
1057 p5 = QPoint( tempPt.x(), tempPt.y() );
1059 p6 = QPoint( tempPt.x(), tempPt.y() );
1063 p1 = QPoint( tempPt.x(), tempPt.y() );
1065 p2 = QPoint( tempPt.x(), tempPt.y() );;
1068 p.drawLine( p1, p2 );
1069 p.drawLine( p3, p4 );
1070 p.drawLine( p5, p6 );
1076 QImage transparentImage = patternImage.copy();
1078 brush.setTextureImage( transparentImage );
1082 brush.setTextureImage( patternImage );
1085 QTransform brushTransform;
1087 brush.setTransform( brushTransform );
1109 map.insert(
"lineangle", QString::number(
mLineAngle ) );
1110 map.insert(
"distance", QString::number(
mDistance ) );
1111 map.insert(
"linewidth", QString::number(
mLineWidth ) );
1113 map.insert(
"offset", QString::number(
mOffset ) );
1137 QDomElement symbolizerElem = doc.createElement(
"se:PolygonSymbolizer" );
1138 if ( !props.value(
"uom",
"" ).isEmpty() )
1139 symbolizerElem.setAttribute(
"uom", props.value(
"uom",
"" ) );
1140 element.appendChild( symbolizerElem );
1145 QDomElement fillElem = doc.createElement(
"se:Fill" );
1146 symbolizerElem.appendChild( fillElem );
1148 QDomElement graphicFillElem = doc.createElement(
"se:GraphicFill" );
1149 fillElem.appendChild( graphicFillElem );
1151 QDomElement graphicElem = doc.createElement(
"se:Graphic" );
1152 graphicFillElem.appendChild( graphicElem );
1159 double angle = props.value(
"angle",
"0" ).toDouble( &ok );
1162 angleFunc = QString(
"%1 + %2" ).arg( props.value(
"angle",
"0" ) ).arg(
mLineAngle );
1166 angleFunc = QString::number( angle +
mLineAngle );
1185 QString featureStyle;
1186 featureStyle.append(
"Brush(" );
1187 featureStyle.append( QString(
"fc:%1" ).arg(
mColor.name() ) );
1188 featureStyle.append( QString(
",bc:%1" ).arg(
"#00000000" ) );
1189 featureStyle.append(
",id:\"ogr-brush-2\"" );
1190 featureStyle.append( QString(
",a:%1" ).arg(
mLineAngle ) );
1191 featureStyle.append( QString(
",s:%1" ).arg(
mLineWidth * widthScaleFactor ) );
1192 featureStyle.append(
",dx:0mm" );
1193 featureStyle.append( QString(
",dy:%1mm" ).arg(
mDistance * widthScaleFactor ) );
1194 featureStyle.append(
")" );
1195 return featureStyle;
1204 if ( !lineAngleExpression && !distanceExpression && !lineWidthExpression && !colorExpression )
1210 if ( lineAngleExpression )
1212 lineAngle = lineAngleExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
1215 if ( distanceExpression )
1217 distance = distanceExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
1220 if ( lineWidthExpression )
1222 lineWidth = lineWidthExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
1225 if ( colorExpression )
1237 QColor fillColor, lineColor;
1240 QDomElement fillElem = element.firstChildElement(
"Fill" );
1241 if ( fillElem.isNull() )
1244 QDomElement graphicFillElem = fillElem.firstChildElement(
"GraphicFill" );
1245 if ( graphicFillElem.isNull() )
1248 QDomElement graphicElem = graphicFillElem.firstChildElement(
"Graphic" );
1249 if ( graphicElem.isNull() )
1255 if ( name !=
"horline" )
1263 double d = angleFunc.toDouble( &ok );
1272 offset = sqrt( pow( vectOffset.x(), 2 ) + pow( vectOffset.y(), 2 ) );
1283 QDomElement strokeElem = element.firstChildElement(
"Stroke" );
1284 if ( !strokeElem.isNull() )
1302 mDisplacementY( 0 ), mDisplacementYUnit(
QgsSymbolV2::MM )
1337 if ( properties.contains(
"distance_x" ) )
1339 layer->
setDistanceX( properties[
"distance_x"].toDouble() );
1341 if ( properties.contains(
"distance_y" ) )
1343 layer->
setDistanceY( properties[
"distance_y"].toDouble() );
1345 if ( properties.contains(
"displacement_x" ) )
1349 if ( properties.contains(
"displacement_y" ) )
1354 if ( properties.contains(
"distance_x_unit" ) )
1358 if ( properties.contains(
"distance_y_unit" ) )
1362 if ( properties.contains(
"displacement_x_unit" ) )
1366 if ( properties.contains(
"displacement_y_unit" ) )
1372 if ( properties.contains(
"distance_x_expression" ) )
1376 if ( properties.contains(
"distance_y_expression" ) )
1380 if ( properties.contains(
"displacement_x_expression" ) )
1384 if ( properties.contains(
"displacement_y_expression" ) )
1393 return "PointPatternFill";
1397 double displacementX,
double displacementY )
1404 if ( width > 10000 || height > 10000 )
1407 brush.setTextureImage( img );
1411 QImage patternImage( width, height, QImage::Format_ARGB32 );
1412 patternImage.fill( 0 );
1416 QPainter p( &patternImage );
1437 double displacementPixelY = displacementY * QgsSymbolLayerV2Utils::pixelSizeScaleFactor( ctx,
mDisplacementYUnit );
1449 QImage transparentImage = patternImage.copy();
1451 brush.setTextureImage( transparentImage );
1455 brush.setTextureImage( patternImage );
1457 QTransform brushTransform;
1459 brush.setTransform( brushTransform );
1484 propertyMap[
"distance_x"] = QString::number(
mDistanceX );
1485 propertyMap[
"distance_y"] = QString::number(
mDistanceY );
1486 propertyMap[
"displacement_x"] = QString::number(
mDisplacementX );
1487 propertyMap[
"displacement_y"] = QString::number(
mDisplacementY );
1511 QDomElement symbolizerElem = doc.createElement(
"se:PolygonSymbolizer" );
1512 if ( !props.value(
"uom",
"" ).isEmpty() )
1513 symbolizerElem.setAttribute(
"uom", props.value(
"uom",
"" ) );
1514 element.appendChild( symbolizerElem );
1519 QDomElement fillElem = doc.createElement(
"se:Fill" );
1520 symbolizerElem.appendChild( fillElem );
1522 QDomElement graphicFillElem = doc.createElement(
"se:GraphicFill" );
1523 fillElem.appendChild( graphicFillElem );
1528 symbolizerElem.appendChild( distanceElem );
1534 QString errorMsg = QString(
"MarkerSymbolLayerV2 expected, %1 found. Skip it." ).arg( layer->
layerType() );
1535 graphicFillElem.appendChild( doc.createComment( errorMsg ) );
1546 Q_UNUSED( element );
1572 if ( !distanceXExpression && !distanceYExpression && !displacementXExpression && !displacementYExpression )
1578 if ( distanceXExpression )
1580 distanceX = distanceXExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
1583 if ( distanceYExpression )
1585 distanceY = distanceYExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
1588 if ( displacementXExpression )
1590 displacementX = displacementXExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
1593 if ( displacementYExpression )
1595 displacementY = displacementYExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
1615 Q_UNUSED( properties );
1621 return "CentroidFill";
1646 double cx = 0, cy = 0;
1647 double area, sum = 0;
1648 for (
int i = points.count() - 1, j = 0; j < points.count(); i = j++ )
1650 const QPointF& p1 = points[i];
1651 const QPointF& p2 = points[j];
1652 area = p1.x() * p2.y() - p1.y() * p2.x();
1654 cx += ( p1.x() + p2.x() ) * area;
1655 cy += ( p1.y() + p2.y() ) * area;
1723 QSet<QString> attributes;