30 #include <QSvgRenderer>
31 #include <QDomDocument>
32 #include <QDomElement>
35 Qt::PenJoinStyle penJoinStyle )
36 : mBrushStyle( style )
37 , mBorderColor( borderColor )
38 , mBorderStyle( borderStyle )
39 , mBorderWidth( borderWidth )
41 , mPenJoinStyle( penJoinStyle )
78 void QgsSimpleFillSymbolLayerV2::applyDataDefinedSymbology(
QgsSymbolV2RenderContext& context, QBrush& brush, QPen& pen, QPen& selPen )
84 if ( colorExpression )
89 if ( fillStyleExpression )
94 if ( colorBorderExpression )
99 if ( widthBorderExpression )
101 double width = widthBorderExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
103 pen.setWidthF( width );
104 selPen.setWidthF( width );
107 if ( borderStyleExpression )
113 if ( joinStyleExpression )
131 if ( props.contains(
"color" ) )
133 if ( props.contains(
"style" ) )
135 if ( props.contains(
"color_border" ) )
140 else if ( props.contains(
"outline_color" ) )
144 else if ( props.contains(
"line_color" ) )
149 if ( props.contains(
"style_border" ) )
154 else if ( props.contains(
"outline_style" ) )
158 else if ( props.contains(
"line_style" ) )
162 if ( props.contains(
"width_border" ) )
165 borderWidth = props[
"width_border"].toDouble();
167 else if ( props.contains(
"outline_width" ) )
169 borderWidth = props[
"outline_width"].toDouble();
171 else if ( props.contains(
"line_width" ) )
173 borderWidth = props[
"line_width"].toDouble();
175 if ( props.contains(
"offset" ) )
177 if ( props.contains(
"joinstyle" ) )
182 if ( props.contains(
"border_width_unit" ) )
186 else if ( props.contains(
"outline_width_unit" ) )
190 else if ( props.contains(
"line_width_unit" ) )
194 if ( props.contains(
"offset_unit" ) )
197 if ( props.contains(
"border_width_map_unit_scale" ) )
199 if ( props.contains(
"offset_map_unit_scale" ) )
202 if ( props.contains(
"color_expression" ) )
206 if ( props.contains(
"color_border_expression" ) )
210 if ( props.contains(
"width_border_expression" ) )
214 if ( props.contains(
"fill_style_expression" ) )
218 if ( props.contains(
"border_style_expression" ) )
222 if ( props.contains(
"join_style_expression" ) )
238 fillColor.setAlphaF( context.
alpha() *
mColor.alphaF() );
243 if ( rasterScaleFactor != 1.0 )
245 mBrush.setMatrix( QMatrix().scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor ) );
259 mPen = QPen( borderColor );
290 p->translate( offset );
297 p->translate( -offset );
336 QDomElement symbolizerElem = doc.createElement(
"se:PolygonSymbolizer" );
337 if ( !props.value(
"uom",
"" ).isEmpty() )
338 symbolizerElem.setAttribute(
"uom", props.value(
"uom",
"" ) );
339 element.appendChild( symbolizerElem );
347 QDomElement fillElem = doc.createElement(
"se:Fill" );
348 symbolizerElem.appendChild( fillElem );
355 QDomElement strokeElem = doc.createElement(
"se:Stroke" );
356 symbolizerElem.appendChild( strokeElem );
369 symbolStyle.append(
";" );
380 Qt::BrushStyle fillStyle;
384 QDomElement fillElem = element.firstChildElement(
"Fill" );
387 QDomElement strokeElem = element.firstChildElement(
"Stroke" );
402 return penBleed + offsetBleed;
409 if ( widthBorderExpression )
411 width = widthBorderExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
419 if ( colorExpression )
434 if ( colorExpression )
451 : mGradientColorType( colorType )
452 , mGradientRamp( NULL )
453 , mGradientType( gradientType )
454 , mCoordinateMode( coordinateMode )
455 , mGradientSpread( spread )
456 , mReferencePoint1( QPointF( 0.5, 0 ) )
457 , mReferencePoint1IsCentroid( false )
458 , mReferencePoint2( QPointF( 0.5, 1 ) )
459 , mReferencePoint2IsCentroid( false )
481 bool refPoint1IsCentroid =
false;
483 bool refPoint2IsCentroid =
false;
488 if ( props.contains(
"type" ) )
490 if ( props.contains(
"coordinate_mode" ) )
492 if ( props.contains(
"spread" ) )
494 if ( props.contains(
"color_type" ) )
496 if ( props.contains(
"gradient_color" ) )
501 else if ( props.contains(
"color" ) )
505 if ( props.contains(
"gradient_color2" ) )
510 if ( props.contains(
"reference_point1" ) )
512 if ( props.contains(
"reference_point1_iscentroid" ) )
513 refPoint1IsCentroid = props[
"reference_point1_iscentroid"].toInt();
514 if ( props.contains(
"reference_point2" ) )
516 if ( props.contains(
"reference_point2_iscentroid" ) )
517 refPoint2IsCentroid = props[
"reference_point2_iscentroid"].toInt();
518 if ( props.contains(
"angle" ) )
519 angle = props[
"angle"].toDouble();
521 if ( props.contains(
"offset" ) )
530 if ( props.contains(
"offset_unit" ) )
532 if ( props.contains(
"offset_map_unit_scale" ) )
543 if ( props.contains(
"color_expression" ) )
545 if ( props.contains(
"color2_expression" ) )
547 if ( props.contains(
"angle_expression" ) )
549 if ( props.contains(
"gradient_type_expression" ) )
551 if ( props.contains(
"coordinate_mode_expression" ) )
553 if ( props.contains(
"spread_expression" ) )
555 if ( props.contains(
"reference1_x_expression" ) )
557 if ( props.contains(
"reference1_y_expression" ) )
559 if ( props.contains(
"reference1_iscentroid_expression" ) )
561 if ( props.contains(
"reference2_x_expression" ) )
563 if ( props.contains(
"reference2_y_expression" ) )
565 if ( props.contains(
"reference2_iscentroid_expression" ) )
579 return "GradientFill";
582 void QgsGradientFillSymbolLayerV2::applyDataDefinedSymbology(
QgsSymbolV2RenderContext& context,
const QPolygonF& points )
596 if ( colorExpression )
602 if ( colorExpression2 )
608 if ( angleExpression )
609 angle = angleExpression->evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
614 if ( typeExpression )
616 QString currentType = typeExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toString();
625 else if ( currentType ==
QObject::tr(
"conical" ) )
639 if ( coordModeExpression )
641 QString currentCoordMode = coordModeExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toString();
642 if ( currentCoordMode ==
QObject::tr(
"feature" ) )
646 else if ( currentCoordMode ==
QObject::tr(
"viewport" ) )
660 if ( spreadExpression )
662 QString currentSpread = spreadExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toString();
667 else if ( currentSpread ==
QObject::tr(
"repeat" ) )
671 else if ( currentSpread ==
QObject::tr(
"reflect" ) )
685 if ( ref1XExpression )
686 refPoint1X = ref1XExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
689 if ( ref1YExpression )
690 refPoint1Y = ref1YExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
693 if ( ref1IsCentroidExpression )
694 refPoint1IsCentroid = ref1IsCentroidExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toBool();
699 if ( ref2XExpression )
700 refPoint2X = ref2XExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
703 if ( ref2YExpression )
704 refPoint2Y = ref2YExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
707 if ( ref2IsCentroidExpression )
708 refPoint2IsCentroid = ref2IsCentroidExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toBool();
710 if ( refPoint1IsCentroid || refPoint2IsCentroid )
715 QRectF bbox = points.boundingRect();
716 double centroidX = ( centroid.x() - bbox.left() ) / bbox.width();
717 double centroidY = ( centroid.y() - bbox.top() ) / bbox.height();
719 if ( refPoint1IsCentroid )
721 refPoint1X = centroidX;
722 refPoint1Y = centroidY;
724 if ( refPoint2IsCentroid )
726 refPoint2X = centroidX;
727 refPoint2Y = centroidY;
733 spread, QPointF( refPoint1X, refPoint1Y ), QPointF( refPoint2X, refPoint2Y ), angle );
736 QPointF QgsGradientFillSymbolLayerV2::rotateReferencePoint(
const QPointF & refPoint,
double angle )
741 QLineF refLine = QLineF( QPointF( 0.5, 0.5 ), refPoint );
743 refLine.setAngle( refLine.angle() +
angle );
745 QPointF rotatedReferencePoint = refLine.p2();
747 if ( rotatedReferencePoint.x() > 1 )
748 rotatedReferencePoint.setX( 1 );
749 if ( rotatedReferencePoint.x() < 0 )
750 rotatedReferencePoint.setX( 0 );
751 if ( rotatedReferencePoint.y() > 1 )
752 rotatedReferencePoint.setY( 1 );
753 if ( rotatedReferencePoint.y() < 0 )
754 rotatedReferencePoint.setY( 0 );
756 return rotatedReferencePoint;
760 const QColor &color,
const QColor &color2,
const GradientColorType &gradientColorType,
762 const GradientCoordinateMode &coordinateMode,
const GradientSpread &gradientSpread,
763 const QPointF &referencePoint1,
const QPointF &referencePoint2,
const double angle )
767 fillColor.setAlphaF( context.
alpha() * fillColor.alphaF() );
768 QColor fillColor2 =
color2;
769 fillColor2.setAlphaF( context.
alpha() * fillColor2.alphaF() );
772 QPointF rotatedReferencePoint1 = angle != 0 ? rotateReferencePoint( referencePoint1, angle ) : referencePoint1;
773 QPointF rotatedReferencePoint2 = angle != 0 ? rotateReferencePoint( referencePoint2, angle ) : referencePoint2;
777 switch ( gradientType )
780 gradient = QLinearGradient( rotatedReferencePoint1, rotatedReferencePoint2 );
783 gradient = QRadialGradient( rotatedReferencePoint1, QLineF( rotatedReferencePoint1, rotatedReferencePoint2 ).length() );
786 gradient = QConicalGradient( rotatedReferencePoint1, QLineF( rotatedReferencePoint1, rotatedReferencePoint2 ).
angle() );
789 switch ( coordinateMode )
792 gradient.setCoordinateMode( QGradient::ObjectBoundingMode );
795 gradient.setCoordinateMode( QGradient::StretchToDeviceMode );
798 switch ( gradientSpread )
801 gradient.setSpread( QGradient::PadSpread );
804 gradient.setSpread( QGradient::ReflectSpread );
807 gradient.setSpread( QGradient::RepeatSpread );
821 gradient.setColorAt( 0.0, fillColor );
822 gradient.setColorAt( 1.0, fillColor2 );
826 brush = QBrush( gradient );
852 applyDataDefinedSymbology( context, points );
855 p->setPen( Qt::NoPen );
862 p->translate( offset );
869 p->translate( -offset );
886 map[
"angle"] = QString::number(
mAngle );
944 int blurRadius,
bool useWholeShape,
double maxDistance ) :
946 mBlurRadius( blurRadius ),
947 mUseWholeShape( useWholeShape ),
948 mMaxDistance( maxDistance ),
950 mColorType( colorType ),
952 mGradientRamp( NULL ),
953 mTwoColorGradientRamp( 0 ),
954 mIgnoreRings( false ),
976 if ( props.contains(
"color_type" ) )
980 if ( props.contains(
"shapeburst_color" ) )
985 else if ( props.contains(
"color" ) )
990 if ( props.contains(
"shapeburst_color2" ) )
995 else if ( props.contains(
"gradient_color2" ) )
999 if ( props.contains(
"blur_radius" ) )
1001 blurRadius = props[
"blur_radius"].toInt();
1003 if ( props.contains(
"use_whole_shape" ) )
1005 useWholeShape = props[
"use_whole_shape"].toInt();
1007 if ( props.contains(
"max_distance" ) )
1009 maxDistance = props[
"max_distance"].toDouble();
1011 if ( props.contains(
"offset" ) )
1022 if ( props.contains(
"offset_unit" ) )
1026 if ( props.contains(
"distance_unit" ) )
1030 if ( props.contains(
"offset_map_unit_scale" ) )
1034 if ( props.contains(
"distance_map_unit_scale" ) )
1038 if ( props.contains(
"ignore_rings" ) )
1047 if ( props.contains(
"color_expression" ) )
1049 if ( props.contains(
"color2_expression" ) )
1051 if ( props.contains(
"blur_radius_expression" ) )
1053 if ( props.contains(
"use_whole_shape_expression" ) )
1055 if ( props.contains(
"max_distance_expression" ) )
1057 if ( props.contains(
"ignore_rings_expression" ) )
1065 return "ShapeburstFill";
1074 void QgsShapeburstFillSymbolLayerV2::applyDataDefinedSymbology(
QgsSymbolV2RenderContext& context, QColor& color, QColor& color2,
int& blurRadius,
bool& useWholeShape,
1075 double& maxDistance,
bool& ignoreRings )
1080 if ( colorExpression )
1086 if ( colorExpression2 )
1092 if ( blurRadiusExpression )
1093 blurRadius = blurRadiusExpression->evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toInt();
1098 if ( useWholeShapeExpression )
1099 useWholeShape = useWholeShapeExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toBool();
1104 if ( maxDistanceExpression )
1105 maxDistance = maxDistanceExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
1110 if ( ignoreRingsExpression )
1111 ignoreRings = ignoreRingsExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toBool();
1127 Q_UNUSED( context );
1147 p->translate( offset );
1152 p->translate( -offset );
1163 applyDataDefinedSymbology( context, color1, color2, blurRadius, useWholeShape, maxDistance, ignoreRings );
1166 int outputPixelMaxDist = 0;
1167 if ( !useWholeShape && maxDistance != 0 )
1181 p->setPen( QPen( Qt::NoPen ) );
1184 int sideBuffer = 4 + ( blurRadius + 2 ) * 4;
1186 double imWidth = points.boundingRect().width() + ( sideBuffer * 2 );
1187 double imHeight = points.boundingRect().height() + ( sideBuffer * 2 );
1193 fillImage->fill( Qt::black );
1196 QImage * alphaImage =
new QImage( fillImage->width(), fillImage->height(), QImage::Format_ARGB32_Premultiplied );
1198 alphaImage->fill( Qt::transparent );
1201 QPainter imgPainter;
1202 imgPainter.begin( alphaImage );
1203 imgPainter.setRenderHint( QPainter::Antialiasing,
true );
1204 imgPainter.setBrush( QBrush( Qt::white ) );
1205 imgPainter.setPen( QPen( Qt::black ) );
1206 imgPainter.translate( -points.boundingRect().left() + sideBuffer, - points.boundingRect().top() + sideBuffer );
1213 imgPainter.begin( fillImage );
1216 imgPainter.drawImage( 0, 0, *alphaImage );
1223 imgPainter.setBrush( QBrush( Qt::white ) );
1224 imgPainter.setPen( QPen( Qt::black ) );
1225 imgPainter.translate( -points.boundingRect().left() + sideBuffer, - points.boundingRect().top() + sideBuffer );
1232 double * dtArray = distanceTransform( fillImage );
1246 if ( blurRadius > 0 )
1252 imgPainter.begin( fillImage );
1253 imgPainter.setCompositionMode( QPainter::CompositionMode_DestinationIn );
1254 imgPainter.drawImage( 0, 0, *alphaImage );
1267 p->translate( offset );
1271 p->drawImage( points.boundingRect().left() - sideBuffer, points.boundingRect().top() - sideBuffer, *fillImage );
1277 p->translate( -offset );
1286 void QgsShapeburstFillSymbolLayerV2::distanceTransform1d(
double *f,
int n,
int *v,
double *z,
double *d )
1292 for (
int q = 1; q <= n - 1; q++ )
1294 double s = (( f[q] + q * q ) - ( f[v[k]] + ( v[k] * v[k] ) ) ) / ( 2 * q - 2 * v[k] );
1298 s = (( f[q] + q * q ) - ( f[v[k]] + ( v[k] * v[k] ) ) ) / ( 2 * q - 2 * v[k] );
1307 for (
int q = 0; q <= n - 1; q++ )
1309 while ( z[k+1] < q )
1311 d[q] = ( q - v[k] ) * ( q - v[k] ) + f[v[k]];
1316 void QgsShapeburstFillSymbolLayerV2::distanceTransform2d(
double * im,
int width,
int height )
1318 int maxDimension = qMax( width, height );
1319 double *f =
new double[ maxDimension ];
1320 int *v =
new int[ maxDimension ];
1321 double *z =
new double[ maxDimension + 1 ];
1322 double *d =
new double[ maxDimension ];
1325 for (
int x = 0; x < width; x++ )
1327 for (
int y = 0; y < height; y++ )
1329 f[y] = im[ x + y * width ];
1331 distanceTransform1d( f, height, v, z, d );
1332 for (
int y = 0; y < height; y++ )
1334 im[ x + y * width ] = d[y];
1339 for (
int y = 0; y < height; y++ )
1341 for (
int x = 0; x < width; x++ )
1343 f[x] = im[ x + y*width ];
1345 distanceTransform1d( f, width, v, z, d );
1346 for (
int x = 0; x < width; x++ )
1348 im[ x + y*width ] = d[x];
1359 double * QgsShapeburstFillSymbolLayerV2::distanceTransform( QImage *im )
1361 int width = im->width();
1362 int height = im->height();
1364 double * dtArray =
new double[width * height];
1369 for (
int heightIndex = 0; heightIndex < height; ++heightIndex )
1371 QRgb* scanLine = ( QRgb* )im->constScanLine( heightIndex );
1372 for (
int widthIndex = 0; widthIndex < width; ++widthIndex )
1374 tmpRgb = scanLine[widthIndex];
1375 if ( qRed( tmpRgb ) == 0 )
1383 dtArray[ idx ] =
INF;
1390 distanceTransform2d( dtArray, width, height );
1395 void QgsShapeburstFillSymbolLayerV2::dtArrayToQImage(
double * array, QImage *im,
QgsVectorColorRampV2* ramp,
double layerAlpha,
bool useWholeShape,
int maxPixelDistance )
1397 int width = im->width();
1398 int height = im->height();
1401 double maxDistanceValue;
1403 if ( useWholeShape )
1406 double dtMaxValue = array[0];
1407 for (
int i = 1; i < ( width * height ); ++i )
1409 if ( array[i] > dtMaxValue )
1411 dtMaxValue = array[i];
1416 maxDistanceValue = sqrt( dtMaxValue );
1421 maxDistanceValue = maxPixelDistance;
1426 double squaredVal = 0;
1429 bool layerHasAlpha = layerAlpha < 1.0;
1431 for (
int heightIndex = 0; heightIndex < height; ++heightIndex )
1433 QRgb* scanLine = ( QRgb* )im->scanLine( heightIndex );
1434 for (
int widthIndex = 0; widthIndex < width; ++widthIndex )
1437 squaredVal = array[idx];
1440 if ( maxDistanceValue > 0 )
1442 pixVal = squaredVal > 0 ? qMin(( sqrt( squaredVal ) / maxDistanceValue ), 1.0 ) : 0;
1450 pixColor = ramp->
color( pixVal );
1452 int pixAlpha = pixColor.alpha();
1453 if (( layerHasAlpha ) || ( pixAlpha != 255 ) )
1456 double alpha = pixAlpha * layerAlpha;
1461 scanLine[widthIndex] = pixColor.rgba();
1472 map[
"color_type"] = QString::number(
mColorType );
1473 map[
"blur_radius"] = QString::number(
mBlurRadius );
1551 , mOutlineWidth( 0.0 )
1573 p->setPen( QPen( Qt::NoPen ) );
1580 p->setBrush( QBrush( selColor ) );
1590 QTransform t =
mBrush.transform();
1592 QBrush rotatedBrush =
mBrush;
1593 rotatedBrush.setTransform( t );
1594 p->setBrush( rotatedBrush );
1602 QList<QPolygonF>::const_iterator ringIt = rings->constBegin();
1603 for ( ; ringIt != rings->constEnd(); ++ringIt )
1663 return subLayerBleed;
1672 if ( widthExpression )
1674 width = widthExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
1681 Q_UNUSED( context );
1684 return QColor( Qt::black );
1691 return Qt::SolidLine;
1695 return Qt::SolidLine;
1708 mPatternWidth( width ),
1715 setDefaultSvgParams();
1720 mPatternWidth( width ),
1722 mSvgData( svgData ),
1729 setDefaultSvgParams();
1781 setDefaultSvgParams();
1791 if ( properties.contains(
"width" ) )
1793 width = properties[
"width"].toDouble();
1795 if ( properties.contains(
"svgFile" ) )
1797 QString svgName = properties[
"svgFile"];
1799 svgFilePath = ( savePath.isEmpty() ? svgName : savePath );
1801 if ( properties.contains(
"angle" ) )
1803 angle = properties[
"angle"].toDouble();
1807 if ( !svgFilePath.isEmpty() )
1813 if ( properties.contains(
"data" ) )
1815 data = QByteArray::fromHex( properties[
"data"].toLocal8Bit() );
1821 if ( properties.contains(
"svgFillColor" ) )
1826 else if ( properties.contains(
"color" ) )
1830 if ( properties.contains(
"svgOutlineColor" ) )
1835 else if ( properties.contains(
"outline_color" ) )
1839 else if ( properties.contains(
"line_color" ) )
1843 if ( properties.contains(
"svgOutlineWidth" ) )
1848 else if ( properties.contains(
"outline_width" ) )
1852 else if ( properties.contains(
"line_width" ) )
1858 if ( properties.contains(
"pattern_width_unit" ) )
1862 if ( properties.contains(
"pattern_width_map_unit_scale" ) )
1866 if ( properties.contains(
"svg_outline_width_unit" ) )
1870 if ( properties.contains(
"svg_outline_width_map_unit_scale" ) )
1874 if ( properties.contains(
"outline_width_unit" ) )
1878 if ( properties.contains(
"outline_width_map_unit_scale" ) )
1883 if ( properties.contains(
"width_expression" ) )
1885 if ( properties.contains(
"svgFile_expression" ) )
1887 if ( properties.contains(
"angle_expression" ) )
1889 if ( properties.contains(
"svgFillColor_expression" ) )
1891 if ( properties.contains(
"svgOutlineColor_expression" ) )
1893 if ( properties.contains(
"svgOutlineWidth_expression" ) )
1904 void QgsSVGFillSymbolLayer::applyPattern( QBrush& brush,
const QString& svgFilePath,
double patternWidth,
QgsSymbolV2::OutputUnit patternWidthUnit,
1905 const QColor& svgFillColor,
const QColor& svgOutlineColor,
double svgOutlineWidth,
1918 if ((
int )size < 1.0 || 10000.0 <
size )
1925 bool fitsInCache =
true;
1933 double hwRatio = 1.0;
1934 if ( patternPict.width() > 0 )
1936 hwRatio = ( double )patternPict.height() / ( double )patternPict.width();
1938 mSvgPattern =
new QImage((
int )size, (
int )( size * hwRatio ), QImage::Format_ARGB32_Premultiplied );
1942 p.drawPicture( QPointF( size / 2, size * hwRatio / 2 ), patternPict );
1945 QTransform brushTransform;
1949 QImage transparentImage = fitsInCache ? patternImage.copy() :
mSvgPattern->copy();
1951 brush.setTextureImage( transparentImage );
1955 brush.setTextureImage( fitsInCache ? patternImage : *
mSvgPattern );
1957 brush.setTransform( brushTransform );
1964 applyPattern(
mBrush,
mSvgFilePath,
mPatternWidth,
mPatternWidthUnit,
mSvgFillColor,
mSvgOutlineColor,
mSvgOutlineWidth,
mSvgOutlineWidthUnit, context,
mPatternWidthMapUnitScale,
mSvgOutlineWidthMapUnitScale );
1991 map.insert(
"data", QString(
mSvgData.toHex() ) );
1995 map.insert(
"angle", QString::number(
mAngle ) );
2046 QDomElement symbolizerElem = doc.createElement(
"se:PolygonSymbolizer" );
2047 if ( !props.value(
"uom",
"" ).isEmpty() )
2048 symbolizerElem.setAttribute(
"uom", props.value(
"uom",
"" ) );
2049 element.appendChild( symbolizerElem );
2053 QDomElement fillElem = doc.createElement(
"se:Fill" );
2054 symbolizerElem.appendChild( fillElem );
2056 QDomElement graphicFillElem = doc.createElement(
"se:GraphicFill" );
2057 fillElem.appendChild( graphicFillElem );
2059 QDomElement graphicElem = doc.createElement(
"se:Graphic" );
2060 graphicFillElem.appendChild( graphicElem );
2070 symbolizerElem.appendChild( doc.createComment(
"SVG from data not implemented yet" ) );
2081 double angle = props.value(
"angle",
"0" ).toDouble( &ok );
2084 angleFunc = QString(
"%1 + %2" ).arg( props.value(
"angle",
"0" ) ).arg(
mAngle );
2086 else if ( angle +
mAngle != 0 )
2088 angleFunc = QString::number( angle +
mAngle );
2105 QString path, mimeType;
2107 Qt::PenStyle penStyle;
2108 double size, borderWidth;
2110 QDomElement fillElem = element.firstChildElement(
"Fill" );
2111 if ( fillElem.isNull() )
2114 QDomElement graphicFillElem = fillElem.firstChildElement(
"GraphicFill" );
2115 if ( graphicFillElem.isNull() )
2118 QDomElement graphicElem = graphicFillElem.firstChildElement(
"Graphic" );
2119 if ( graphicElem.isNull() )
2125 if ( mimeType !=
"image/svg+xml" )
2135 double d = angleFunc.toDouble( &ok );
2146 QDomElement strokeElem = element.firstChildElement(
"Stroke" );
2147 if ( !strokeElem.isNull() )
2169 if ( !widthExpression && !svgFileExpression && !fillColorExpression && !outlineColorExpression && !outlineWidthExpression && !angleExpression )
2174 if ( angleExpression )
2180 if ( widthExpression )
2182 width = widthExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
2185 if ( svgFileExpression )
2187 svgFile = svgFileExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toString();
2190 if ( fillColorExpression )
2195 if ( outlineColorExpression )
2200 if ( outlineWidthExpression )
2202 outlineWidth = outlineWidthExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
2209 void QgsSVGFillSymbolLayer::storeViewBox()
2225 void QgsSVGFillSymbolLayer::setDefaultSvgParams()
2237 bool hasFillParam, hasOutlineParam, hasOutlineWidthParam;
2238 QColor defaultFillColor, defaultOutlineColor;
2239 double defaultOutlineWidth;
2241 defaultOutlineWidth );
2247 if ( hasOutlineParam )
2251 if ( hasOutlineWidthParam )
2264 , mLineAngle( 45.0 )
2267 , mFillLineSymbol( 0 )
2287 delete mFillLineSymbol;
2302 delete mFillLineSymbol;
2303 mFillLineSymbol = lineSymbol;
2314 return mFillLineSymbol;
2367 QColor
color( Qt::black );
2370 if ( properties.contains(
"lineangle" ) )
2373 lineAngle = properties[
"lineangle"].toDouble();
2375 else if ( properties.contains(
"angle" ) )
2377 lineAngle = properties[
"angle"].toDouble();
2381 if ( properties.contains(
"distance" ) )
2383 distance = properties[
"distance"].toDouble();
2387 if ( properties.contains(
"linewidth" ) )
2390 lineWidth = properties[
"linewidth"].toDouble();
2392 else if ( properties.contains(
"outline_width" ) )
2394 lineWidth = properties[
"outline_width"].toDouble();
2396 else if ( properties.contains(
"line_width" ) )
2398 lineWidth = properties[
"line_width"].toDouble();
2402 if ( properties.contains(
"color" ) )
2406 else if ( properties.contains(
"outline_color" ) )
2410 else if ( properties.contains(
"line_color" ) )
2416 if ( properties.contains(
"offset" ) )
2418 offset = properties[
"offset"].toDouble();
2423 if ( properties.contains(
"distance_unit" ) )
2427 if ( properties.contains(
"distance_map_unit_scale" ) )
2431 if ( properties.contains(
"line_width_unit" ) )
2435 else if ( properties.contains(
"outline_width_unit" ) )
2439 if ( properties.contains(
"line_width_map_unit_scale" ) )
2443 if ( properties.contains(
"offset_unit" ) )
2447 if ( properties.contains(
"offset_map_unit_scale" ) )
2451 if ( properties.contains(
"outline_width_unit" ) )
2455 if ( properties.contains(
"outline_width_map_unit_scale" ) )
2462 if ( properties.contains(
"lineangle_expression" ) )
2466 if ( properties.contains(
"distance_expression" ) )
2470 if ( properties.contains(
"linewidth_expression" ) )
2474 if ( properties.contains(
"color_expression" ) )
2478 return patternLayer;
2483 return "LinePatternFill";
2486 void QgsLinePatternFillSymbolLayer::applyPattern(
const QgsSymbolV2RenderContext& context, QBrush& brush,
double lineAngle,
double distance,
2487 double lineWidth,
const QColor& color )
2489 Q_UNUSED( lineWidth );
2492 mBrush.setTextureImage( QImage() );
2494 if ( !mFillLineSymbol )
2500 if ( !fillLineSymbol )
2512 double outputPixelBleed = 0;
2513 double outputPixelInterval = 0;
2525 outputPixelBleed = qMax( outputPixelBleed, outputPixelLayerBleed );
2528 if ( markerLineLayer )
2537 outputPixelInterval = qMax( outputPixelInterval, outputPixelLayerInterval );
2541 if ( outputPixelInterval > 0 )
2545 double intervalScale = qRound( outputPixelInterval ) / outputPixelInterval;
2546 outputPixelInterval = qRound( outputPixelInterval );
2553 if ( markerLineLayer )
2564 height = outputPixelDist;
2565 width = outputPixelInterval > 0 ? outputPixelInterval : height;
2569 width = outputPixelDist;
2570 height = outputPixelInterval > 0 ? outputPixelInterval : width;
2574 height = outputPixelDist / cos( lineAngle *
M_PI / 180 );
2575 width = outputPixelDist / sin( lineAngle *
M_PI / 180 );
2578 lineAngle = 180 * atan2((
double ) height, (
double ) width ) /
M_PI;
2579 if ( lineAngle < 0 )
2584 height = qAbs( height );
2585 width = qAbs( width );
2587 outputPixelDist = height * cos( lineAngle *
M_PI / 180 );
2591 int offsetHeight = qRound( qAbs( outputPixelOffset / cos( lineAngle *
M_PI / 180 ) ) );
2592 outputPixelOffset = offsetHeight * cos( lineAngle *
M_PI / 180 );
2601 int bufferMulti = qMax( qCeil( outputPixelBleed / width ), qCeil( outputPixelBleed / width ) );
2605 bufferMulti = qMax( bufferMulti, 1 );
2607 int xBuffer = width * bufferMulti;
2608 int yBuffer = height * bufferMulti;
2609 int innerWidth = width;
2610 int innerHeight = height;
2611 width += 2 * xBuffer;
2612 height += 2 * yBuffer;
2614 if ( width > 10000 || height > 10000 )
2619 QImage patternImage( width, height, QImage::Format_ARGB32 );
2620 patternImage.fill( 0 );
2622 QPointF p1, p2, p3, p4, p5, p6;
2625 p1 = QPointF( 0, yBuffer );
2626 p2 = QPointF( width, yBuffer );
2627 p3 = QPointF( 0, yBuffer + innerHeight );
2628 p4 = QPointF( width, yBuffer + innerHeight );
2632 p1 = QPointF( xBuffer, height );
2633 p2 = QPointF( xBuffer, 0 );
2634 p3 = QPointF( xBuffer + innerWidth, height );
2635 p4 = QPointF( xBuffer + innerWidth, 0 );
2637 else if ( lineAngle > 0 && lineAngle < 90 )
2639 dx = outputPixelDist * cos(( 90 - lineAngle ) *
M_PI / 180.0 );
2640 dy = outputPixelDist * sin(( 90 - lineAngle ) *
M_PI / 180.0 );
2641 p1 = QPointF( 0, height );
2642 p2 = QPointF( width, 0 );
2643 p3 = QPointF( -dx, height - dy );
2644 p4 = QPointF( width - dx, -dy );
2645 p5 = QPointF( dx, height + dy );
2646 p6 = QPointF( width + dx, dy );
2648 else if ( lineAngle > 180 && lineAngle < 270 )
2650 dx = outputPixelDist * cos(( 90 - lineAngle ) *
M_PI / 180.0 );
2651 dy = outputPixelDist * sin(( 90 - lineAngle ) *
M_PI / 180.0 );
2652 p1 = QPointF( width, 0 );
2653 p2 = QPointF( 0, height );
2654 p3 = QPointF( width - dx, -dy );
2655 p4 = QPointF( -dx, height - dy );
2656 p5 = QPointF( width + dx, dy );
2657 p6 = QPointF( dx, height + dy );
2659 else if ( lineAngle > 90 && lineAngle < 180 )
2661 dy = outputPixelDist * cos(( 180 - lineAngle ) *
M_PI / 180 );
2662 dx = outputPixelDist * sin(( 180 - lineAngle ) *
M_PI / 180 );
2663 p1 = QPointF( 0, 0 );
2664 p2 = QPointF( width, height );
2665 p5 = QPointF( dx, -dy );
2666 p6 = QPointF( width + dx, height - dy );
2667 p3 = QPointF( -dx, dy );
2668 p4 = QPointF( width - dx, height + dy );
2670 else if ( lineAngle > 270 && lineAngle < 360 )
2672 dy = outputPixelDist * cos(( 180 - lineAngle ) *
M_PI / 180 );
2673 dx = outputPixelDist * sin(( 180 - lineAngle ) *
M_PI / 180 );
2674 p1 = QPointF( width, height );
2675 p2 = QPointF( 0, 0 );
2676 p5 = QPointF( width + dx, height - dy );
2677 p6 = QPointF( dx, -dy );
2678 p3 = QPointF( width - dx, height + dy );
2679 p4 = QPointF( -dx, dy );
2686 p3 = QPointF( tempPt.x(), tempPt.y() );
2688 p4 = QPointF( tempPt.x(), tempPt.y() );
2690 p5 = QPointF( tempPt.x(), tempPt.y() );
2692 p6 = QPointF( tempPt.x(), tempPt.y() );
2696 p1 = QPointF( tempPt.x(), tempPt.y() );
2698 p2 = QPointF( tempPt.x(), tempPt.y() );;
2701 QPainter p( &patternImage );
2705 p.setRenderHint( QPainter::Antialiasing,
false );
2706 QPen pen( QColor( Qt::black ) );
2707 pen.setWidthF( 0.1 );
2708 pen.setCapStyle( Qt::FlatCap );
2713 QPolygon polygon = QPolygon() << QPoint( 0, 0 ) << QPoint( width - 1, 0 ) << QPoint( width - 1, height - 1 ) << QPoint( 0, height - 1 ) << QPoint( 0, 0 );
2714 p.drawPolygon( polygon );
2716 polygon = QPolygon() << QPoint( xBuffer, yBuffer ) << QPoint( width - xBuffer - 1, yBuffer ) << QPoint( width - xBuffer - 1, height - yBuffer - 1 ) << QPoint( xBuffer, height - yBuffer - 1 ) << QPoint( xBuffer, yBuffer );
2717 p.drawPolygon( polygon );
2723 p.setRenderHint( QPainter::Antialiasing,
true );
2736 QVector<QPolygonF> polygons;
2737 polygons.append( QPolygonF() << p1 << p2 );
2738 polygons.append( QPolygonF() << p3 << p4 );
2741 polygons.append( QPolygonF() << p5 << p6 );
2744 foreach ( QPolygonF polygon, polygons )
2749 fillLineSymbol->
stopRender( lineRenderContext );
2753 patternImage = patternImage.copy( xBuffer, yBuffer, patternImage.width() - 2 * xBuffer, patternImage.height() - 2 * yBuffer );
2758 QImage transparentImage = patternImage.copy();
2760 brush.setTextureImage( transparentImage );
2764 brush.setTextureImage( patternImage );
2767 QTransform brushTransform;
2769 brush.setTransform( brushTransform );
2771 delete fillLineSymbol;
2778 if ( mFillLineSymbol )
2793 map.insert(
"angle", QString::number(
mLineAngle ) );
2794 map.insert(
"distance", QString::number(
mDistance ) );
2795 map.insert(
"line_width", QString::number(
mLineWidth ) );
2797 map.insert(
"offset", QString::number(
mOffset ) );
2813 if ( mFillLineSymbol )
2822 QDomElement symbolizerElem = doc.createElement(
"se:PolygonSymbolizer" );
2823 if ( !props.value(
"uom",
"" ).isEmpty() )
2824 symbolizerElem.setAttribute(
"uom", props.value(
"uom",
"" ) );
2825 element.appendChild( symbolizerElem );
2830 QDomElement fillElem = doc.createElement(
"se:Fill" );
2831 symbolizerElem.appendChild( fillElem );
2833 QDomElement graphicFillElem = doc.createElement(
"se:GraphicFill" );
2834 fillElem.appendChild( graphicFillElem );
2836 QDomElement graphicElem = doc.createElement(
"se:Graphic" );
2837 graphicFillElem.appendChild( graphicElem );
2840 QColor lineColor = mFillLineSymbol ? mFillLineSymbol->
color() : QColor();
2841 double lineWidth = mFillLineSymbol ? mFillLineSymbol->
width() : 0.0;
2847 double angle = props.value(
"angle",
"0" ).toDouble( &ok );
2850 angleFunc = QString(
"%1 + %2" ).arg( props.value(
"angle",
"0" ) ).arg(
mLineAngle );
2854 angleFunc = QString::number( angle +
mLineAngle );
2865 QString featureStyle;
2866 featureStyle.append(
"Brush(" );
2867 featureStyle.append( QString(
"fc:%1" ).arg(
mColor.name() ) );
2868 featureStyle.append( QString(
",bc:%1" ).arg(
"#00000000" ) );
2869 featureStyle.append(
",id:\"ogr-brush-2\"" );
2870 featureStyle.append( QString(
",a:%1" ).arg(
mLineAngle ) );
2871 featureStyle.append( QString(
",s:%1" ).arg(
mLineWidth * widthScaleFactor ) );
2872 featureStyle.append(
",dx:0mm" );
2873 featureStyle.append( QString(
",dy:%1mm" ).arg(
mDistance * widthScaleFactor ) );
2874 featureStyle.append(
")" );
2875 return featureStyle;
2884 if ( !lineAngleExpression && !distanceExpression && !lineWidthExpression && !colorExpression )
2890 if ( lineAngleExpression )
2892 lineAngle = lineAngleExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
2895 if ( distanceExpression )
2897 distance = distanceExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
2900 if ( lineWidthExpression )
2902 lineWidth = lineWidthExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
2905 if ( colorExpression )
2909 applyPattern( context,
mBrush, lineAngle, distance, lineWidth, color );
2919 Qt::PenStyle lineStyle;
2921 QDomElement fillElem = element.firstChildElement(
"Fill" );
2922 if ( fillElem.isNull() )
2925 QDomElement graphicFillElem = fillElem.firstChildElement(
"GraphicFill" );
2926 if ( graphicFillElem.isNull() )
2929 QDomElement graphicElem = graphicFillElem.firstChildElement(
"Graphic" );
2930 if ( graphicElem.isNull() )
2936 if ( name !=
"horline" )
2944 double d = angleFunc.toDouble( &ok );
2953 offset = sqrt( pow( vectOffset.x(), 2 ) + pow( vectOffset.y(), 2 ) );
2964 QDomElement strokeElem = element.firstChildElement(
"Stroke" );
2965 if ( !strokeElem.isNull() )
2984 mDisplacementY( 0 ), mDisplacementYUnit(
QgsSymbolV2::MM )
3042 if ( properties.contains(
"distance_x" ) )
3044 layer->
setDistanceX( properties[
"distance_x"].toDouble() );
3046 if ( properties.contains(
"distance_y" ) )
3048 layer->
setDistanceY( properties[
"distance_y"].toDouble() );
3050 if ( properties.contains(
"displacement_x" ) )
3054 if ( properties.contains(
"displacement_y" ) )
3059 if ( properties.contains(
"distance_x_unit" ) )
3063 if ( properties.contains(
"distance_x_map_unit_scale" ) )
3067 if ( properties.contains(
"distance_y_unit" ) )
3071 if ( properties.contains(
"distance_y_map_unit_scale" ) )
3075 if ( properties.contains(
"displacement_x_unit" ) )
3079 if ( properties.contains(
"displacement_x_map_unit_scale" ) )
3083 if ( properties.contains(
"displacement_y_unit" ) )
3087 if ( properties.contains(
"displacement_y_map_unit_scale" ) )
3091 if ( properties.contains(
"outline_width_unit" ) )
3095 if ( properties.contains(
"outline_width_map_unit_scale" ) )
3101 if ( properties.contains(
"distance_x_expression" ) )
3105 if ( properties.contains(
"distance_y_expression" ) )
3109 if ( properties.contains(
"displacement_x_expression" ) )
3113 if ( properties.contains(
"displacement_y_expression" ) )
3122 return "PointPatternFill";
3125 void QgsPointPatternFillSymbolLayer::applyPattern(
const QgsSymbolV2RenderContext& context, QBrush& brush,
double distanceX,
double distanceY,
3126 double displacementX,
double displacementY )
3133 if ( width > 10000 || height > 10000 )
3136 brush.setTextureImage( img );
3140 QImage patternImage( width, height, QImage::Format_ARGB32 );
3141 patternImage.fill( 0 );
3145 QPainter p( &patternImage );
3179 QImage transparentImage = patternImage.copy();
3181 brush.setTextureImage( transparentImage );
3185 brush.setTextureImage( patternImage );
3187 QTransform brushTransform;
3189 brush.setTransform( brushTransform );
3214 map.insert(
"distance_x", QString::number(
mDistanceX ) );
3215 map.insert(
"distance_y", QString::number(
mDistanceY ) );
3216 map.insert(
"displacement_x", QString::number(
mDisplacementX ) );
3217 map.insert(
"displacement_y", QString::number(
mDisplacementY ) );
3246 QDomElement symbolizerElem = doc.createElement(
"se:PolygonSymbolizer" );
3247 if ( !props.value(
"uom",
"" ).isEmpty() )
3248 symbolizerElem.setAttribute(
"uom", props.value(
"uom",
"" ) );
3249 element.appendChild( symbolizerElem );
3254 QDomElement fillElem = doc.createElement(
"se:Fill" );
3255 symbolizerElem.appendChild( fillElem );
3257 QDomElement graphicFillElem = doc.createElement(
"se:GraphicFill" );
3258 fillElem.appendChild( graphicFillElem );
3263 symbolizerElem.appendChild( distanceElem );
3269 QString errorMsg = QString(
"MarkerSymbolLayerV2 expected, %1 found. Skip it." ).arg( layer->
layerType() );
3270 graphicFillElem.appendChild( doc.createComment( errorMsg ) );
3281 Q_UNUSED( element );
3310 if ( !distanceXExpression && !distanceYExpression && !displacementXExpression && !displacementYExpression )
3317 if ( distanceXExpression )
3319 distanceX = distanceXExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
3322 if ( distanceYExpression )
3324 distanceY = distanceYExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
3327 if ( displacementXExpression )
3329 displacementX = displacementXExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
3332 if ( displacementYExpression )
3334 displacementY = displacementYExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
3336 applyPattern( context,
mBrush, distanceX, distanceY, displacementX, displacementY );
3371 if ( properties.contains(
"point_on_surface" ) )
3379 return "CentroidFill";
3471 QSet<QString> attributes;
3520 , mImageFilePath( imageFilePath )
3544 if ( properties.contains(
"imageFile" ) )
3546 imagePath = properties[
"imageFile"];
3548 if ( properties.contains(
"coordinate_mode" ) )
3552 if ( properties.contains(
"alpha" ) )
3554 alpha = properties[
"alpha"].toDouble();
3556 if ( properties.contains(
"offset" ) )
3560 if ( properties.contains(
"angle" ) )
3562 angle = properties[
"angle"].toDouble();
3564 if ( properties.contains(
"width" ) )
3566 width = properties[
"width"].toDouble();
3574 if ( properties.contains(
"offset_unit" ) )
3578 if ( properties.contains(
"offset_map_unit_scale" ) )
3582 if ( properties.contains(
"width_unit" ) )
3586 if ( properties.contains(
"width_map_unit_scale" ) )
3592 if ( properties.contains(
"file_expression" ) )
3596 if ( properties.contains(
"alpha_expression" ) )
3600 if ( properties.contains(
"angle_expression" ) )
3604 if ( properties.contains(
"width_expression" ) )
3619 return "RasterFill";
3635 p->translate( offset );
3639 QRectF boundingRect = points.boundingRect();
3640 mBrush.setTransform(
mBrush.transform().translate( boundingRect.left() -
mBrush.transform().dx(),
3641 boundingRect.top() -
mBrush.transform().dy() ) );
3647 p->translate( -offset );
3659 Q_UNUSED( context );
3667 map[
"alpha"] = QString::number(
mAlpha );
3671 map[
"angle"] = QString::number(
mAngle );
3672 map[
"width"] = QString::number(
mWidth );
3726 if ( !widthExpression && !angleExpression && !alphaExpression && !fileExpression )
3731 if ( angleExpression )
3736 if ( !widthExpression && !alphaExpression && !fileExpression )
3742 if ( widthExpression )
3744 width = widthExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
3747 if ( alphaExpression )
3749 alpha = alphaExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
3752 if ( fileExpression )
3754 file = fileExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toString();
3756 applyPattern(
mBrush, file, width, alpha, context );
3759 void QgsRasterFillSymbolLayer::applyPattern( QBrush &brush,
const QString &imageFilePath,
const double width,
const double alpha,
const QgsSymbolV2RenderContext &context )
3761 QImage image( imageFilePath );
3762 if ( image.isNull() )
3766 if ( !image.hasAlphaChannel() )
3768 image = image.convertToFormat( QImage::Format_ARGB32 );
3778 pixelWidth = image.width();
3786 p.setCompositionMode( QPainter::CompositionMode_DestinationIn );
3787 QColor alphaColor( 0, 0, 0 );
3788 alphaColor.setAlphaF( alpha );
3789 p.fillRect( image.rect(), alphaColor );
3796 image = image.scaledToWidth( pixelWidth, Qt::SmoothTransformation );
3799 brush.setTextureImage( image );