44#include <QPagedPaintDevice>
46#include <QSvgRenderer>
47#include <QDomDocument>
54 Qt::PenJoinStyle penJoinStyle )
55 : mBrushStyle( style )
56 , mStrokeColor( strokeColor )
57 , mStrokeStyle( strokeStyle )
58 , mStrokeWidth( strokeWidth )
59 , mPenJoinStyle( penJoinStyle )
103void QgsSimpleFillSymbolLayer::applyDataDefinedSymbology(
QgsSymbolRenderContext &context, QBrush &brush, QPen &pen, QPen &selPen )
128 penColor.setAlphaF( context.
opacity() * penColor.alphaF() );
129 pen.setColor( penColor );
137 double width = exprVal.toDouble( &ok );
141 pen.setWidthF( width );
142 selPen.setWidthF( width );
179 if ( props.contains( QStringLiteral(
"color" ) ) )
181 if ( props.contains( QStringLiteral(
"style" ) ) )
183 if ( props.contains( QStringLiteral(
"color_border" ) ) )
188 else if ( props.contains( QStringLiteral(
"outline_color" ) ) )
192 else if ( props.contains( QStringLiteral(
"line_color" ) ) )
197 if ( props.contains( QStringLiteral(
"style_border" ) ) )
202 else if ( props.contains( QStringLiteral(
"outline_style" ) ) )
206 else if ( props.contains( QStringLiteral(
"line_style" ) ) )
210 if ( props.contains( QStringLiteral(
"width_border" ) ) )
213 strokeWidth = props[QStringLiteral(
"width_border" )].toDouble();
215 else if ( props.contains( QStringLiteral(
"outline_width" ) ) )
217 strokeWidth = props[QStringLiteral(
"outline_width" )].toDouble();
219 else if ( props.contains( QStringLiteral(
"line_width" ) ) )
221 strokeWidth = props[QStringLiteral(
"line_width" )].toDouble();
223 if ( props.contains( QStringLiteral(
"offset" ) ) )
225 if ( props.contains( QStringLiteral(
"joinstyle" ) ) )
230 if ( props.contains( QStringLiteral(
"border_width_unit" ) ) )
234 else if ( props.contains( QStringLiteral(
"outline_width_unit" ) ) )
238 else if ( props.contains( QStringLiteral(
"line_width_unit" ) ) )
242 if ( props.contains( QStringLiteral(
"offset_unit" ) ) )
245 if ( props.contains( QStringLiteral(
"border_width_map_unit_scale" ) ) )
247 if ( props.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
250 sl->restoreOldDataDefinedProperties( props );
258 return QStringLiteral(
"SimpleFill" );
270 selColor.setAlphaF( context.
opacity() );
329 if (
mBrush.style() == Qt::SolidPattern ||
mBrush.style() == Qt::NoBrush || !
dynamic_cast<QPagedPaintDevice *
>( p->device() ) )
341 p->setPen( Qt::NoPen );
345 p->setBrush( Qt::NoBrush );
362 map[QStringLiteral(
"outline_width" )] = QString::number(
mStrokeWidth );
390 QDomElement symbolizerElem = doc.createElement( QStringLiteral(
"se:PolygonSymbolizer" ) );
391 if ( !props.value( QStringLiteral(
"uom" ), QString() ).toString().isEmpty() )
392 symbolizerElem.setAttribute( QStringLiteral(
"uom" ), props.value( QStringLiteral(
"uom" ), QString() ).toString() );
393 element.appendChild( symbolizerElem );
402 bool exportOk {
false };
406 if ( ! image.isNull() )
409 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
410 symbolizerElem.appendChild( fillElem );
411 QDomElement graphicFillElem = doc.createElement( QStringLiteral(
"se:GraphicFill" ) );
412 fillElem.appendChild( graphicFillElem );
413 QDomElement graphicElem = doc.createElement( QStringLiteral(
"se:Graphic" ) );
414 graphicFillElem.appendChild( graphicElem );
416 const QFileInfo info { context.exportFilePath() };
417 QString pngPath { info.completeSuffix().isEmpty() ? context.exportFilePath() : context.exportFilePath().chopped( info.completeSuffix().length() ).append( QStringLiteral(
"png" ) ) };
419 image.save( pngPath );
434 const double alpha { props.value( QStringLiteral(
"alpha" ), QVariant() ).toDouble( &ok ) };
440 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
441 symbolizerElem.appendChild( fillElem );
448 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
449 symbolizerElem.appendChild( strokeElem );
453 const double alpha { props.value( QStringLiteral(
"alpha" ), QVariant() ).toDouble( &ok ) };
473 symbolStyle.append(
';' );
482 Qt::BrushStyle fillStyle;
486 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
489 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
495 double scaleFactor = 1.0;
496 const QString uom = element.attribute( QStringLiteral(
"uom" ) );
503 sl->setOutputUnit( sldUnitSize );
512 return penBleed + offsetBleed;
570 QPixmap pixmap( QSize( 32, 32 ) );
571 pixmap.fill( Qt::transparent );
573 painter.begin( &pixmap );
574 painter.setRenderHint( QPainter::Antialiasing );
582 std::unique_ptr< QgsSimpleFillSymbolLayer > layerClone(
clone() );
583 layerClone->setStrokeStyle( Qt::PenStyle::NoPen );
584 layerClone->drawPreviewIcon( symbolContext, pixmap.size() );
586 return pixmap.toImage();
594 : mGradientColorType( colorType )
595 , mGradientType( gradientType )
596 , mCoordinateMode( coordinateMode )
597 , mGradientSpread( spread )
598 , mReferencePoint1( QPointF( 0.5, 0 ) )
599 , mReferencePoint2( QPointF( 0.5, 1 ) )
620 bool refPoint1IsCentroid =
false;
622 bool refPoint2IsCentroid =
false;
627 if ( props.contains( QStringLiteral(
"type" ) ) )
629 if ( props.contains( QStringLiteral(
"coordinate_mode" ) ) )
631 if ( props.contains( QStringLiteral(
"spread" ) ) )
633 if ( props.contains( QStringLiteral(
"color_type" ) ) )
635 if ( props.contains( QStringLiteral(
"gradient_color" ) ) )
640 else if ( props.contains( QStringLiteral(
"color" ) ) )
644 if ( props.contains( QStringLiteral(
"gradient_color2" ) ) )
649 if ( props.contains( QStringLiteral(
"reference_point1" ) ) )
651 if ( props.contains( QStringLiteral(
"reference_point1_iscentroid" ) ) )
652 refPoint1IsCentroid = props[QStringLiteral(
"reference_point1_iscentroid" )].toInt();
653 if ( props.contains( QStringLiteral(
"reference_point2" ) ) )
655 if ( props.contains( QStringLiteral(
"reference_point2_iscentroid" ) ) )
656 refPoint2IsCentroid = props[QStringLiteral(
"reference_point2_iscentroid" )].toInt();
657 if ( props.contains( QStringLiteral(
"angle" ) ) )
658 angle = props[QStringLiteral(
"angle" )].toDouble();
660 if ( props.contains( QStringLiteral(
"offset" ) ) )
677 if ( props.contains( QStringLiteral(
"offset_unit" ) ) )
679 if ( props.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
682 sl->setReferencePoint1IsCentroid( refPoint1IsCentroid );
684 sl->setReferencePoint2IsCentroid( refPoint2IsCentroid );
685 sl->setAngle(
angle );
687 sl->setColorRamp( gradientRamp );
689 sl->restoreOldDataDefinedProperties( props );
702 return QStringLiteral(
"GradientFill" );
705void QgsGradientFillSymbolLayer::applyDataDefinedSymbology(
QgsSymbolRenderContext &context,
const QPolygonF &points )
750 if ( currentType == QObject::tr(
"linear" ) )
754 else if ( currentType == QObject::tr(
"radial" ) )
758 else if ( currentType == QObject::tr(
"conical" ) )
772 if ( currentCoordMode == QObject::tr(
"feature" ) )
776 else if ( currentCoordMode == QObject::tr(
"viewport" ) )
790 if ( currentSpread == QObject::tr(
"pad" ) )
794 else if ( currentSpread == QObject::tr(
"repeat" ) )
798 else if ( currentSpread == QObject::tr(
"reflect" ) )
845 if ( refPoint1IsCentroid || refPoint2IsCentroid )
850 QRectF bbox = points.boundingRect();
851 double centroidX = ( centroid.
x() - bbox.left() ) / bbox.width();
852 double centroidY = ( centroid.
y() - bbox.top() ) / bbox.height();
854 if ( refPoint1IsCentroid )
856 refPoint1X = centroidX;
857 refPoint1Y = centroidY;
859 if ( refPoint2IsCentroid )
861 refPoint2X = centroidX;
862 refPoint2Y = centroidY;
868 spread, QPointF( refPoint1X, refPoint1Y ), QPointF( refPoint2X, refPoint2Y ),
angle );
871QPointF QgsGradientFillSymbolLayer::rotateReferencePoint( QPointF refPoint,
double angle )
876 QLineF refLine = QLineF( QPointF( 0.5, 0.5 ), refPoint );
878 refLine.setAngle( refLine.angle() +
angle );
880 QPointF rotatedReferencePoint = refLine.p2();
882 if ( rotatedReferencePoint.x() > 1 )
883 rotatedReferencePoint.setX( 1 );
884 if ( rotatedReferencePoint.x() < 0 )
885 rotatedReferencePoint.setX( 0 );
886 if ( rotatedReferencePoint.y() > 1 )
887 rotatedReferencePoint.setY( 1 );
888 if ( rotatedReferencePoint.y() < 0 )
889 rotatedReferencePoint.setY( 0 );
891 return rotatedReferencePoint;
898 QPointF referencePoint1, QPointF referencePoint2,
const double angle )
903 QColor fillColor2 =
color2;
904 fillColor2.setAlphaF( context.
opacity() * fillColor2.alphaF() );
915 gradient = QLinearGradient( rotatedReferencePoint1, rotatedReferencePoint2 );
918 gradient = QRadialGradient( rotatedReferencePoint1, QLineF( rotatedReferencePoint1, rotatedReferencePoint2 ).length() );
921 gradient = QConicalGradient( rotatedReferencePoint1, QLineF( rotatedReferencePoint1, rotatedReferencePoint2 ).
angle() );
927 gradient.setCoordinateMode( QGradient::ObjectBoundingMode );
930 gradient.setCoordinateMode( QGradient::StretchToDeviceMode );
936 gradient.setSpread( QGradient::PadSpread );
939 gradient.setSpread( QGradient::ReflectSpread );
942 gradient.setSpread( QGradient::RepeatSpread );
958 gradient.setColorAt( 1.0, fillColor2 );
962 brush = QBrush( gradient );
969 selColor.setAlphaF( context.
opacity() );
986 applyDataDefinedSymbology( context, points );
990 p->setPen( Qt::NoPen );
1023 map[QStringLiteral(
"color_type" )] = QString::number(
static_cast< int >(
mGradientColorType ) );
1024 map[QStringLiteral(
"type" )] = QString::number(
static_cast<int>(
mGradientType ) );
1025 map[QStringLiteral(
"coordinate_mode" )] = QString::number(
static_cast< int >(
mCoordinateMode ) );
1026 map[QStringLiteral(
"spread" )] = QString::number(
static_cast< int >(
mGradientSpread ) );
1031 map[QStringLiteral(
"angle" )] = QString::number(
mAngle );
1057 return sl.release();
1099 int blurRadius,
bool useWholeShape,
double maxDistance )
1100 : mBlurRadius( blurRadius )
1101 , mUseWholeShape( useWholeShape )
1102 , mMaxDistance( maxDistance )
1103 , mColorType( colorType )
1122 if ( props.contains( QStringLiteral(
"color_type" ) ) )
1126 if ( props.contains( QStringLiteral(
"shapeburst_color" ) ) )
1131 else if ( props.contains( QStringLiteral(
"color" ) ) )
1136 if ( props.contains( QStringLiteral(
"shapeburst_color2" ) ) )
1141 else if ( props.contains( QStringLiteral(
"gradient_color2" ) ) )
1145 if ( props.contains( QStringLiteral(
"blur_radius" ) ) )
1147 blurRadius = props[QStringLiteral(
"blur_radius" )].toInt();
1149 if ( props.contains( QStringLiteral(
"use_whole_shape" ) ) )
1151 useWholeShape = props[QStringLiteral(
"use_whole_shape" )].toInt();
1153 if ( props.contains( QStringLiteral(
"max_distance" ) ) )
1155 maxDistance = props[QStringLiteral(
"max_distance" )].toDouble();
1157 if ( props.contains( QStringLiteral(
"offset" ) ) )
1176 if ( props.contains( QStringLiteral(
"offset_unit" ) ) )
1180 if ( props.contains( QStringLiteral(
"distance_unit" ) ) )
1184 if ( props.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
1188 if ( props.contains( QStringLiteral(
"distance_map_unit_scale" ) ) )
1192 if ( props.contains( QStringLiteral(
"ignore_rings" ) ) )
1194 sl->setIgnoreRings( props[QStringLiteral(
"ignore_rings" )].toInt() );
1198 sl->setColorRamp( gradientRamp );
1201 sl->restoreOldDataDefinedProperties( props );
1203 return sl.release();
1208 return QStringLiteral(
"ShapeburstFill" );
1213 if ( mGradientRamp.get() == ramp )
1216 mGradientRamp.reset( ramp );
1219void QgsShapeburstFillSymbolLayer::applyDataDefinedSymbology(
QgsSymbolRenderContext &context, QColor &color, QColor &color2,
int &blurRadius,
bool &useWholeShape,
1220 double &maxDistance,
bool &ignoreRings )
1277 selColor.setAlphaF( context.
opacity() );
1278 mSelBrush = QBrush( selColor );
1295 if ( useSelectedColor )
1298 p->setBrush( mSelBrush );
1299 QPointF
offset = mOffset;
1334 int outputPixelMaxDist = 0;
1342 std::unique_ptr< QgsGradientColorRamp > twoColorGradientRamp;
1345 twoColorGradientRamp = std::make_unique< QgsGradientColorRamp >( color1,
color2 );
1349 p->setPen( QPen( Qt::NoPen ) );
1354 int pointsWidth =
static_cast< int >( std::round( points.boundingRect().width() ) );
1355 int pointsHeight =
static_cast< int >( std::round( points.boundingRect().height() ) );
1356 int imWidth = pointsWidth + ( sideBuffer * 2 );
1357 int imHeight = pointsHeight + ( sideBuffer * 2 );
1363 std::unique_ptr< QImage > fillImage = std::make_unique< QImage >( imWidth,
1364 imHeight, QImage::Format_ARGB32_Premultiplied );
1365 if ( fillImage->isNull() )
1375 std::unique_ptr< QImage > alphaImage = std::make_unique< QImage >( fillImage->width(), fillImage->height(), QImage::Format_ARGB32_Premultiplied );
1376 if ( alphaImage->isNull() )
1388 fillImage->fill( Qt::black );
1394 alphaImage->fill( Qt::transparent );
1400 QPainter imgPainter;
1401 imgPainter.begin( alphaImage.get() );
1402 imgPainter.setRenderHint( QPainter::Antialiasing,
true );
1403 imgPainter.setBrush( QBrush( Qt::white ) );
1404 imgPainter.setPen( QPen( Qt::black ) );
1405 imgPainter.translate( -points.boundingRect().left() + sideBuffer, - points.boundingRect().top() + sideBuffer );
1414 imgPainter.begin( fillImage.get() );
1417 imgPainter.drawImage( 0, 0, *alphaImage );
1424 imgPainter.setBrush( QBrush( Qt::white ) );
1425 imgPainter.setPen( QPen( Qt::black ) );
1426 imgPainter.translate( -points.boundingRect().left() + sideBuffer, - points.boundingRect().top() + sideBuffer );
1435 double *dtArray = distanceTransform( fillImage.get(), context.
renderContext() );
1455 imgPainter.begin( fillImage.get() );
1456 imgPainter.setCompositionMode( QPainter::CompositionMode_DestinationIn );
1457 imgPainter.drawImage( 0, 0, *alphaImage );
1465 QPointF
offset = mOffset;
1482 p->drawImage( points.boundingRect().left() - sideBuffer, points.boundingRect().top() - sideBuffer, *fillImage );
1493void QgsShapeburstFillSymbolLayer::distanceTransform1d(
double *f,
int n,
int *v,
double *z,
double *d )
1499 for (
int q = 1; q <= n - 1; q++ )
1501 double s = ( ( f[q] +
static_cast< double >( q ) * q ) - ( f[v[k]] + (
static_cast< double >( v[k] ) * v[k] ) ) ) / ( 2 * q - 2 * v[k] );
1505 s = ( ( f[q] +
static_cast< double >( q ) * q ) - ( f[v[k]] + (
static_cast< double >( v[k] ) * v[k] ) ) ) / ( 2 * q - 2 * v[k] );
1514 for (
int q = 0; q <= n - 1; q++ )
1516 while ( z[k + 1] < q )
1518 d[q] =
static_cast< double >( q - v[k] ) * ( q - v[k] ) + f[v[k]];
1523void QgsShapeburstFillSymbolLayer::distanceTransform2d(
double *im,
int width,
int height,
QgsRenderContext &context )
1525 int maxDimension = std::max( width, height );
1526 double *f =
new double[ maxDimension ];
1527 int *v =
new int[ maxDimension ];
1528 double *z =
new double[ maxDimension + 1 ];
1529 double *d =
new double[ maxDimension ];
1532 for (
int x = 0; x < width; x++ )
1537 for (
int y = 0; y < height; y++ )
1539 f[y] = im[ x +
static_cast< std::size_t
>( y ) * width ];
1541 distanceTransform1d( f, height, v, z, d );
1542 for (
int y = 0; y < height; y++ )
1544 im[ x +
static_cast< std::size_t
>( y ) * width ] = d[y];
1549 for (
int y = 0; y < height; y++ )
1554 for (
int x = 0; x < width; x++ )
1556 f[x] = im[ x +
static_cast< std::size_t
>( y ) * width ];
1558 distanceTransform1d( f, width, v, z, d );
1559 for (
int x = 0; x < width; x++ )
1561 im[ x +
static_cast< std::size_t
>( y ) * width ] = d[x];
1572double *QgsShapeburstFillSymbolLayer::distanceTransform( QImage *im,
QgsRenderContext &context )
1574 int width = im->width();
1575 int height = im->height();
1577 double *dtArray =
new double[
static_cast< std::size_t
>( width ) * height];
1581 std::size_t idx = 0;
1582 for (
int heightIndex = 0; heightIndex < height; ++heightIndex )
1587 const QRgb *scanLine =
reinterpret_cast< const QRgb *
>( im->constScanLine( heightIndex ) );
1588 for (
int widthIndex = 0; widthIndex < width; ++widthIndex )
1590 tmpRgb = scanLine[widthIndex];
1591 if ( qRed( tmpRgb ) == 0 )
1599 dtArray[ idx ] =
INF;
1606 distanceTransform2d( dtArray, width, height, context );
1611void QgsShapeburstFillSymbolLayer::dtArrayToQImage(
double *array, QImage *im,
QgsColorRamp *ramp,
QgsRenderContext &context,
bool useWholeShape,
int maxPixelDistance )
1613 int width = im->width();
1614 int height = im->height();
1617 double maxDistanceValue;
1622 double dtMaxValue = array[0];
1623 for ( std::size_t i = 1; i < static_cast< std::size_t >( width ) * height; ++i )
1625 if ( array[i] > dtMaxValue )
1627 dtMaxValue = array[i];
1632 maxDistanceValue = std::sqrt( dtMaxValue );
1637 maxDistanceValue = maxPixelDistance;
1641 std::size_t idx = 0;
1642 double squaredVal = 0;
1645 for (
int heightIndex = 0; heightIndex < height; ++heightIndex )
1650 QRgb *scanLine =
reinterpret_cast< QRgb *
>( im->scanLine( heightIndex ) );
1651 for (
int widthIndex = 0; widthIndex < width; ++widthIndex )
1654 squaredVal = array[idx];
1657 if ( maxDistanceValue > 0 )
1659 pixVal = squaredVal > 0 ? std::min( ( std::sqrt( squaredVal ) / maxDistanceValue ), 1.0 ) : 0;
1668 scanLine[widthIndex] = qPremultiply( ramp->
color( pixVal ).rgba() );
1679 map[QStringLiteral(
"color_type" )] = QString::number(
static_cast< int >( mColorType ) );
1680 map[QStringLiteral(
"blur_radius" )] = QString::number( mBlurRadius );
1681 map[QStringLiteral(
"use_whole_shape" )] = QString::number( mUseWholeShape );
1682 map[QStringLiteral(
"max_distance" )] = QString::number( mMaxDistance );
1685 map[QStringLiteral(
"ignore_rings" )] = QString::number( mIgnoreRings );
1689 if ( mGradientRamp )
1691 map.insert( mGradientRamp->properties() );
1699 std::unique_ptr< QgsShapeburstFillSymbolLayer > sl = std::make_unique< QgsShapeburstFillSymbolLayer >(
mColor, mColor2, mColorType, mBlurRadius, mUseWholeShape, mMaxDistance );
1700 if ( mGradientRamp )
1702 sl->setColorRamp( mGradientRamp->clone() );
1704 sl->setDistanceUnit( mDistanceUnit );
1705 sl->setDistanceMapUnitScale( mDistanceMapUnitScale );
1706 sl->setIgnoreRings( mIgnoreRings );
1707 sl->setOffset( mOffset );
1708 sl->setOffsetUnit( mOffsetUnit );
1709 sl->setOffsetMapUnitScale( mOffsetMapUnitScale );
1712 return sl.release();
1717 double offsetBleed = context.
convertToPainterUnits( std::max( std::fabs( mOffset.x() ), std::fabs( mOffset.y() ) ), mOffsetUnit, mOffsetMapUnitScale );
1728 mDistanceUnit = unit;
1734 if ( mDistanceUnit == mOffsetUnit )
1736 return mDistanceUnit;
1749 mDistanceMapUnitScale = scale;
1750 mOffsetMapUnitScale = scale;
1755 if ( mDistanceMapUnitScale == mOffsetMapUnitScale )
1757 return mDistanceMapUnitScale;
1782 p->setPen( QPen( Qt::NoPen ) );
1784 QTransform bkTransform =
mBrush.transform();
1788 QTransform t =
mBrush.transform();
1789 t.translate( leftCorner.x(), leftCorner.y() );
1790 mBrush.setTransform( t );
1794 QTransform t =
mBrush.transform();
1795 t.translate( 0, 0 );
1796 mBrush.setTransform( t );
1800 if ( useSelectedColor )
1803 p->setBrush( QBrush( selColor ) );
1809 QTransform t =
mBrush.transform();
1811 mBrush.setTransform( t );
1816 mBrush.setTransform( bkTransform );
1852 return Qt::SolidLine;
1856 return Qt::SolidLine;
1860 return mStroke->dxfPenStyle();
1896 , mPatternWidth( width )
1900 mColor = QColor( 255, 255, 255 );
1906 , mPatternWidth( width )
1907 , mSvgData( svgData )
1912 mColor = QColor( 255, 255, 255 );
1913 setDefaultSvgParams();
1921 mPatternWidthUnit = unit;
1922 mSvgStrokeWidthUnit = unit;
1925 mStroke->setOutputUnit( unit );
1931 if ( mPatternWidthUnit != unit || mSvgStrokeWidthUnit != unit ||
mStrokeWidthUnit != unit )
1941 mPatternWidthMapUnitScale = scale;
1942 mSvgStrokeWidthMapUnitScale = scale;
1948 mPatternWidthMapUnitScale == mSvgStrokeWidthMapUnitScale &&
1951 return mPatternWidthMapUnitScale;
1961 mSvgFilePath = svgPath;
1962 setDefaultSvgParams();
1972 if (
properties.contains( QStringLiteral(
"width" ) ) )
1974 width =
properties[QStringLiteral(
"width" )].toDouble();
1976 if (
properties.contains( QStringLiteral(
"svgFile" ) ) )
1980 if (
properties.contains( QStringLiteral(
"angle" ) ) )
1985 std::unique_ptr< QgsSVGFillSymbolLayer > symbolLayer;
1988 symbolLayer = std::make_unique< QgsSVGFillSymbolLayer >(
svgFilePath, width,
angle );
1992 if (
properties.contains( QStringLiteral(
"data" ) ) )
1994 data = QByteArray::fromHex(
properties[QStringLiteral(
"data" )].toString().toLocal8Bit() );
1996 symbolLayer = std::make_unique< QgsSVGFillSymbolLayer >( data, width,
angle );
2000 if (
properties.contains( QStringLiteral(
"svgFillColor" ) ) )
2005 else if (
properties.contains( QStringLiteral(
"color" ) ) )
2009 if (
properties.contains( QStringLiteral(
"svgOutlineColor" ) ) )
2014 else if (
properties.contains( QStringLiteral(
"outline_color" ) ) )
2018 else if (
properties.contains( QStringLiteral(
"line_color" ) ) )
2022 if (
properties.contains( QStringLiteral(
"svgOutlineWidth" ) ) )
2025 symbolLayer->setSvgStrokeWidth(
properties[QStringLiteral(
"svgOutlineWidth" )].toDouble() );
2027 else if (
properties.contains( QStringLiteral(
"outline_width" ) ) )
2029 symbolLayer->setSvgStrokeWidth(
properties[QStringLiteral(
"outline_width" )].toDouble() );
2031 else if (
properties.contains( QStringLiteral(
"line_width" ) ) )
2033 symbolLayer->setSvgStrokeWidth(
properties[QStringLiteral(
"line_width" )].toDouble() );
2037 if (
properties.contains( QStringLiteral(
"pattern_width_unit" ) ) )
2041 if (
properties.contains( QStringLiteral(
"pattern_width_map_unit_scale" ) ) )
2045 if (
properties.contains( QStringLiteral(
"svg_outline_width_unit" ) ) )
2049 if (
properties.contains( QStringLiteral(
"svg_outline_width_map_unit_scale" ) ) )
2053 if (
properties.contains( QStringLiteral(
"outline_width_unit" ) ) )
2057 if (
properties.contains( QStringLiteral(
"outline_width_map_unit_scale" ) ) )
2062 if (
properties.contains( QStringLiteral(
"parameters" ) ) )
2068 symbolLayer->restoreOldDataDefinedProperties(
properties );
2070 return symbolLayer.release();
2075 QVariantMap::iterator it =
properties.find( QStringLiteral(
"svgFile" ) );
2087 return QStringLiteral(
"SVGFill" );
2090void QgsSVGFillSymbolLayer::applyPattern( QBrush &brush,
const QString &svgFilePath,
double patternWidth,
Qgis::RenderUnit patternWidthUnit,
2091 const QColor &svgFillColor,
const QColor &svgStrokeColor,
double svgStrokeWidth,
2095 if ( mSvgViewBox.isNull() )
2102 if (
static_cast< int >( size ) < 1.0 || 10000.0 < size )
2104 brush.setTextureImage( QImage() );
2108 bool fitsInCache =
true;
2116 double hwRatio = 1.0;
2117 if ( patternPict.width() > 0 )
2119 hwRatio =
static_cast< double >( patternPict.height() ) /
static_cast< double >( patternPict.width() );
2121 patternImage = QImage(
static_cast< int >( size ),
static_cast< int >( size * hwRatio ), QImage::Format_ARGB32_Premultiplied );
2122 patternImage.fill( 0 );
2124 QPainter p( &patternImage );
2125 p.drawPicture( QPointF( size / 2, size * hwRatio / 2 ), patternPict );
2128 QTransform brushTransform;
2131 QImage transparentImage = patternImage.copy();
2133 brush.setTextureImage( transparentImage );
2137 brush.setTextureImage( patternImage );
2139 brush.setTransform( brushTransform );
2147 applyPattern(
mBrush, mSvgFilePath, mPatternWidth, mPatternWidthUnit,
mColor, mSvgStrokeColor, mSvgStrokeWidth, mSvgStrokeWidthUnit, context, mPatternWidthMapUnitScale, mSvgStrokeWidthMapUnitScale, evaluatedParameters );
2170 mStroke->renderPolyline( points, context.
feature(), context.
renderContext(), -1, useSelectedColor );
2173 for (
auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
2175 mStroke->renderPolyline( *ringIt, context.
feature(), context.
renderContext(), -1, useSelectedColor );
2184 if ( !mSvgFilePath.isEmpty() )
2186 map.insert( QStringLiteral(
"svgFile" ), mSvgFilePath );
2190 map.insert( QStringLiteral(
"data" ), QString( mSvgData.toHex() ) );
2193 map.insert( QStringLiteral(
"width" ), QString::number( mPatternWidth ) );
2194 map.insert( QStringLiteral(
"angle" ), QString::number(
mAngle ) );
2199 map.insert( QStringLiteral(
"outline_width" ), QString::number( mSvgStrokeWidth ) );
2216 std::unique_ptr< QgsSVGFillSymbolLayer > clonedLayer;
2217 if ( !mSvgFilePath.isEmpty() )
2219 clonedLayer = std::make_unique< QgsSVGFillSymbolLayer >( mSvgFilePath, mPatternWidth,
mAngle );
2220 clonedLayer->setSvgFillColor(
mColor );
2221 clonedLayer->setSvgStrokeColor( mSvgStrokeColor );
2222 clonedLayer->setSvgStrokeWidth( mSvgStrokeWidth );
2226 clonedLayer = std::make_unique< QgsSVGFillSymbolLayer >( mSvgData, mPatternWidth,
mAngle );
2229 clonedLayer->setPatternWidthUnit( mPatternWidthUnit );
2230 clonedLayer->setPatternWidthMapUnitScale( mPatternWidthMapUnitScale );
2231 clonedLayer->setSvgStrokeWidthUnit( mSvgStrokeWidthUnit );
2232 clonedLayer->setSvgStrokeWidthMapUnitScale( mSvgStrokeWidthMapUnitScale );
2236 clonedLayer->setParameters( mParameters );
2240 clonedLayer->setSubSymbol( mStroke->clone() );
2244 return clonedLayer.release();
2249 QDomElement symbolizerElem = doc.createElement( QStringLiteral(
"se:PolygonSymbolizer" ) );
2250 if ( !props.value( QStringLiteral(
"uom" ), QString() ).toString().isEmpty() )
2251 symbolizerElem.setAttribute( QStringLiteral(
"uom" ), props.value( QStringLiteral(
"uom" ), QString() ).toString() );
2252 element.appendChild( symbolizerElem );
2256 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2257 symbolizerElem.appendChild( fillElem );
2259 QDomElement graphicFillElem = doc.createElement( QStringLiteral(
"se:GraphicFill" ) );
2260 fillElem.appendChild( graphicFillElem );
2262 QDomElement graphicElem = doc.createElement( QStringLiteral(
"se:Graphic" ) );
2263 graphicFillElem.appendChild( graphicElem );
2265 if ( !mSvgFilePath.isEmpty() )
2276 symbolizerElem.appendChild( doc.createComment( QStringLiteral(
"SVG from data not implemented yet" ) ) );
2282 double angle = props.value( QStringLiteral(
"angle" ), QStringLiteral(
"0" ) ).toDouble( &ok );
2285 angleFunc = QStringLiteral(
"%1 + %2" ).arg( props.value( QStringLiteral(
"angle" ), QStringLiteral(
"0" ) ).toString() ).arg(
mAngle );
2298 mStroke->toSld( doc, element, props );
2310 return mStroke.get();
2317 mStroke.reset(
nullptr );
2330 mStroke.reset( lineSymbol );
2340 if ( mStroke && mStroke->symbolLayer( 0 ) )
2342 double subLayerBleed = mStroke->symbolLayer( 0 )->estimateMaxBleed( context );
2343 return subLayerBleed;
2353 return QColor( Qt::black );
2355 return mStroke->color();
2362 attr.unite( mStroke->usedAttributes( context ) );
2370 if ( mStroke && mStroke->hasDataDefinedProperties() )
2377 QString path, mimeType;
2379 Qt::PenStyle penStyle;
2380 double size, strokeWidth;
2382 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
2383 if ( fillElem.isNull() )
2386 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
2387 if ( graphicFillElem.isNull() )
2390 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
2391 if ( graphicElem.isNull() )
2397 if ( mimeType != QLatin1String(
"image/svg+xml" ) )
2402 double scaleFactor = 1.0;
2403 const QString uom = element.attribute( QStringLiteral(
"uom" ) );
2405 size = size * scaleFactor;
2406 strokeWidth = strokeWidth * scaleFactor;
2413 double d = angleFunc.toDouble( &ok );
2418 std::unique_ptr< QgsSVGFillSymbolLayer > sl = std::make_unique< QgsSVGFillSymbolLayer >( path, size,
angle );
2419 sl->setOutputUnit( sldUnitSize );
2422 sl->setSvgStrokeWidth( strokeWidth );
2425 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
2426 if ( !strokeElem.isNull() )
2437 return sl.release();
2455 double width = mPatternWidth;
2461 QString svgFile = mSvgFilePath;
2480 double strokeWidth = mSvgStrokeWidth;
2489 mSvgStrokeWidthUnit, context, mPatternWidthMapUnitScale, mSvgStrokeWidthMapUnitScale, evaluatedParameters );
2493void QgsSVGFillSymbolLayer::storeViewBox()
2495 if ( !mSvgData.isEmpty() )
2497 QSvgRenderer r( mSvgData );
2500 mSvgViewBox = r.viewBoxF();
2505 mSvgViewBox = QRectF();
2508void QgsSVGFillSymbolLayer::setDefaultSvgParams()
2510 if ( mSvgFilePath.isEmpty() )
2515 bool hasFillParam, hasFillOpacityParam, hasStrokeParam, hasStrokeWidthParam, hasStrokeOpacityParam;
2516 bool hasDefaultFillColor, hasDefaultFillOpacity, hasDefaultStrokeColor, hasDefaultStrokeWidth, hasDefaultStrokeOpacity;
2517 QColor defaultFillColor, defaultStrokeColor;
2518 double defaultStrokeWidth, defaultFillOpacity, defaultStrokeOpacity;
2520 hasFillOpacityParam, hasDefaultFillOpacity, defaultFillOpacity,
2521 hasStrokeParam, hasDefaultStrokeColor, defaultStrokeColor,
2522 hasStrokeWidthParam, hasDefaultStrokeWidth, defaultStrokeWidth,
2523 hasStrokeOpacityParam, hasDefaultStrokeOpacity, defaultStrokeOpacity );
2525 double newFillOpacity = hasFillOpacityParam ?
mColor.alphaF() : 1.0;
2526 double newStrokeOpacity = hasStrokeOpacityParam ? mSvgStrokeColor.alphaF() : 1.0;
2528 if ( hasDefaultFillColor )
2530 mColor = defaultFillColor;
2531 mColor.setAlphaF( newFillOpacity );
2533 if ( hasDefaultFillOpacity )
2535 mColor.setAlphaF( defaultFillOpacity );
2537 if ( hasDefaultStrokeColor )
2539 mSvgStrokeColor = defaultStrokeColor;
2540 mSvgStrokeColor.setAlphaF( newStrokeOpacity );
2542 if ( hasDefaultStrokeOpacity )
2544 mSvgStrokeColor.setAlphaF( defaultStrokeOpacity );
2546 if ( hasDefaultStrokeWidth )
2548 mSvgStrokeWidth = defaultStrokeWidth;
2561 mFillLineSymbol = std::make_unique<QgsLineSymbol>( );
2569 mFillLineSymbol->setWidth( w );
2575 mFillLineSymbol->setColor(
c );
2581 return mFillLineSymbol ? mFillLineSymbol->color() :
mColor;
2593 mFillLineSymbol.reset( qgis::down_cast<QgsLineSymbol *>( symbol ) );
2602 return mFillLineSymbol.get();
2608 if ( mFillLineSymbol )
2609 attr.unite( mFillLineSymbol->usedAttributes( context ) );
2617 if ( mFillLineSymbol && mFillLineSymbol->hasDataDefinedProperties() )
2639 double lineAngleRad { qDegreesToRadians( mLineAngle ) };
2641 const int quadrant {
static_cast<int>( lineAngleRad / M_PI_2 ) };
2642 Q_ASSERT( quadrant >= 0 && quadrant <= 3 );
2652 lineAngleRad -= M_PI / 2;
2657 lineAngleRad -= M_PI;
2662 lineAngleRad -= M_PI + M_PI_2;
2670 QSize size {
static_cast<int>( distancePx ),
static_cast<int>( distancePx ) };
2672 if (
static_cast<int>( mLineAngle ) % 90 != 0 )
2674 size = QSize(
static_cast<int>( distancePx / std::sin( lineAngleRad ) ),
static_cast<int>( distancePx / std::cos( lineAngleRad ) ) );
2677 QPixmap pixmap( size );
2678 pixmap.fill( Qt::transparent );
2680 painter.begin( &pixmap );
2681 painter.setRenderHint( QPainter::Antialiasing );
2689 std::unique_ptr< QgsLinePatternFillSymbolLayer > layerClone(
clone() );
2690 layerClone->setOffset( 0 );
2691 layerClone->drawPreviewIcon( symbolContext, pixmap.size() );
2693 return pixmap.toImage();
2705 mDistanceUnit = unit;
2706 mLineWidthUnit = unit;
2709 if ( mFillLineSymbol )
2710 mFillLineSymbol->setOutputUnit( unit );
2733 mDistanceMapUnitScale = scale;
2734 mLineWidthMapUnitScale = scale;
2735 mOffsetMapUnitScale = scale;
2741 mDistanceMapUnitScale == mLineWidthMapUnitScale &&
2742 mLineWidthMapUnitScale == mOffsetMapUnitScale )
2744 return mDistanceMapUnitScale;
2751 std::unique_ptr< QgsLinePatternFillSymbolLayer > patternLayer = std::make_unique< QgsLinePatternFillSymbolLayer >();
2757 QColor
color( Qt::black );
2760 if (
properties.contains( QStringLiteral(
"lineangle" ) ) )
2765 else if (
properties.contains( QStringLiteral(
"angle" ) ) )
2769 patternLayer->setLineAngle(
lineAngle );
2771 if (
properties.contains( QStringLiteral(
"distance" ) ) )
2775 patternLayer->setDistance(
distance );
2777 if (
properties.contains( QStringLiteral(
"linewidth" ) ) )
2782 else if (
properties.contains( QStringLiteral(
"outline_width" ) ) )
2786 else if (
properties.contains( QStringLiteral(
"line_width" ) ) )
2790 patternLayer->setLineWidth(
lineWidth );
2792 if (
properties.contains( QStringLiteral(
"color" ) ) )
2796 else if (
properties.contains( QStringLiteral(
"outline_color" ) ) )
2800 else if (
properties.contains( QStringLiteral(
"line_color" ) ) )
2804 patternLayer->setColor(
color );
2806 if (
properties.contains( QStringLiteral(
"offset" ) ) )
2810 patternLayer->setOffset(
offset );
2813 if (
properties.contains( QStringLiteral(
"distance_unit" ) ) )
2817 if (
properties.contains( QStringLiteral(
"distance_map_unit_scale" ) ) )
2821 if (
properties.contains( QStringLiteral(
"line_width_unit" ) ) )
2825 else if (
properties.contains( QStringLiteral(
"outline_width_unit" ) ) )
2829 if (
properties.contains( QStringLiteral(
"line_width_map_unit_scale" ) ) )
2833 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
2837 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
2841 if (
properties.contains( QStringLiteral(
"outline_width_unit" ) ) )
2845 if (
properties.contains( QStringLiteral(
"outline_width_map_unit_scale" ) ) )
2849 if (
properties.contains( QStringLiteral(
"coordinate_reference" ) ) )
2853 if (
properties.contains( QStringLiteral(
"clip_mode" ) ) )
2858 patternLayer->restoreOldDataDefinedProperties(
properties );
2860 return patternLayer.release();
2865 return QStringLiteral(
"LinePatternFill" );
2868bool QgsLinePatternFillSymbolLayer::applyPattern(
const QgsSymbolRenderContext &context, QBrush &brush,
double lineAngle,
double distance )
2870 mBrush.setTextureImage( QImage() );
2872 if ( !mFillLineSymbol )
2877 std::unique_ptr< QgsLineSymbol > fillLineSymbol( mFillLineSymbol->clone() );
2878 if ( !fillLineSymbol )
2894 outputPixelOffset = std::fmod( outputPixelOffset, outputPixelDist );
2895 if ( outputPixelOffset > outputPixelDist / 2.0 )
2896 outputPixelOffset -= outputPixelDist;
2900 double outputPixelBleed = 0;
2901 double outputPixelInterval = 0;
2902 for (
int i = 0; i < fillLineSymbol->symbolLayerCount(); i++ )
2906 outputPixelBleed = std::max( outputPixelBleed, outputPixelLayerBleed );
2909 if ( markerLineLayer )
2918 outputPixelInterval = std::max( outputPixelInterval, outputPixelLayerInterval );
2922 if ( outputPixelInterval > 0 )
2926 double intervalScale = std::round( outputPixelInterval ) / outputPixelInterval;
2927 outputPixelInterval = std::round( outputPixelInterval );
2929 for (
int i = 0; i < fillLineSymbol->symbolLayerCount(); i++ )
2934 if ( markerLineLayer )
2948 height = outputPixelDist;
2949 width = outputPixelInterval > 0 ? outputPixelInterval : height;
2953 width = outputPixelDist;
2954 height = outputPixelInterval > 0 ? outputPixelInterval : width;
2958 height = outputPixelDist / std::cos(
lineAngle * M_PI / 180 );
2959 width = outputPixelDist / std::sin(
lineAngle * M_PI / 180 );
2962 lineAngle = 180 * std::atan2(
static_cast< double >( height ),
static_cast< double >( width ) ) / M_PI;
2968 height = std::abs( height );
2969 width = std::abs( width );
2971 outputPixelDist = std::abs( height * std::cos(
lineAngle * M_PI / 180 ) );
2975 int offsetHeight =
static_cast< int >( std::round( outputPixelOffset / std::cos(
lineAngle * M_PI / 180 ) ) );
2976 outputPixelOffset = offsetHeight * std::cos(
lineAngle * M_PI / 180 );
2985 int bufferMulti =
static_cast< int >( std::max( std::ceil( outputPixelBleed / width ), std::ceil( outputPixelBleed / width ) ) );
2989 bufferMulti = std::max( bufferMulti, 1 );
2991 int xBuffer = width * bufferMulti;
2992 int yBuffer = height * bufferMulti;
2993 int innerWidth = width;
2994 int innerHeight = height;
2995 width += 2 * xBuffer;
2996 height += 2 * yBuffer;
2999 if ( width > 2000 || height > 2000 || width == 0 || height == 0 )
3004 QImage patternImage( width, height, QImage::Format_ARGB32 );
3005 patternImage.fill( 0 );
3007 QPointF p1, p2, p3, p4, p5, p6;
3010 p1 = QPointF( 0, yBuffer );
3011 p2 = QPointF( width, yBuffer );
3012 p3 = QPointF( 0, yBuffer + innerHeight );
3013 p4 = QPointF( width, yBuffer + innerHeight );
3017 p1 = QPointF( xBuffer, height );
3018 p2 = QPointF( xBuffer, 0 );
3019 p3 = QPointF( xBuffer + innerWidth, height );
3020 p4 = QPointF( xBuffer + innerWidth, 0 );
3024 dx = outputPixelDist * std::cos( ( 90 -
lineAngle ) * M_PI / 180.0 );
3025 dy = outputPixelDist * std::sin( ( 90 -
lineAngle ) * M_PI / 180.0 );
3026 p1 = QPointF( 0, height );
3027 p2 = QPointF( width, 0 );
3028 p3 = QPointF( -dx, height - dy );
3029 p4 = QPointF( width - dx, -dy );
3030 p5 = QPointF( dx, height + dy );
3031 p6 = QPointF( width + dx, dy );
3035 dx = outputPixelDist * std::cos( ( 90 -
lineAngle ) * M_PI / 180.0 );
3036 dy = outputPixelDist * std::sin( ( 90 -
lineAngle ) * M_PI / 180.0 );
3037 p1 = QPointF( width, 0 );
3038 p2 = QPointF( 0, height );
3039 p3 = QPointF( width - dx, -dy );
3040 p4 = QPointF( -dx, height - dy );
3041 p5 = QPointF( width + dx, dy );
3042 p6 = QPointF( dx, height + dy );
3046 dy = outputPixelDist * std::cos( ( 180 -
lineAngle ) * M_PI / 180 );
3047 dx = outputPixelDist * std::sin( ( 180 -
lineAngle ) * M_PI / 180 );
3048 p1 = QPointF( 0, 0 );
3049 p2 = QPointF( width, height );
3050 p5 = QPointF( dx, -dy );
3051 p6 = QPointF( width + dx, height - dy );
3052 p3 = QPointF( -dx, dy );
3053 p4 = QPointF( width - dx, height + dy );
3057 dy = outputPixelDist * std::cos( ( 180 -
lineAngle ) * M_PI / 180 );
3058 dx = outputPixelDist * std::sin( ( 180 -
lineAngle ) * M_PI / 180 );
3059 p1 = QPointF( width, height );
3060 p2 = QPointF( 0, 0 );
3061 p5 = QPointF( width + dx, height - dy );
3062 p6 = QPointF( dx, -dy );
3063 p3 = QPointF( width - dx, height + dy );
3064 p4 = QPointF( -dx, dy );
3071 p3 = QPointF( tempPt.x(), tempPt.y() );
3073 p4 = QPointF( tempPt.x(), tempPt.y() );
3075 p5 = QPointF( tempPt.x(), tempPt.y() );
3077 p6 = QPointF( tempPt.x(), tempPt.y() );
3081 p1 = QPointF( tempPt.x(), tempPt.y() );
3083 p2 = QPointF( tempPt.x(), tempPt.y() );
3086 QPainter p( &patternImage );
3090 p.setRenderHint( QPainter::Antialiasing,
false );
3091 QPen pen( QColor( Qt::black ) );
3092 pen.setWidthF( 0.1 );
3093 pen.setCapStyle( Qt::FlatCap );
3098 QPolygon polygon = QPolygon() << QPoint( 0, 0 ) << QPoint( width - 1, 0 ) << QPoint( width - 1, height - 1 ) << QPoint( 0, height - 1 ) << QPoint( 0, 0 );
3099 p.drawPolygon( polygon );
3101 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 );
3102 p.drawPolygon( polygon );
3108 p.setRenderHint( QPainter::Antialiasing,
true );
3121 fillLineSymbol->startRender( lineRenderContext, context.
fields() );
3123 QVector<QPolygonF> polygons;
3124 polygons.append( QPolygonF() << p1 << p2 );
3125 polygons.append( QPolygonF() << p3 << p4 );
3128 polygons.append( QPolygonF() << p5 << p6 );
3132 for (
const QPolygonF &polygon : std::as_const( polygons ) )
3134 fillLineSymbol->renderPolyline( polygon, context.
feature(), lineRenderContext, -1, useSelectedColor );
3137 fillLineSymbol->stopRender( lineRenderContext );
3141 patternImage = patternImage.copy( xBuffer, yBuffer, patternImage.width() - 2 * xBuffer, patternImage.height() - 2 * yBuffer );
3146 QImage transparentImage = patternImage.copy();
3148 brush.setTextureImage( transparentImage );
3152 brush.setTextureImage( patternImage );
3155 QTransform brushTransform;
3156 brush.setTransform( brushTransform );
3166 || ( mFillLineSymbol && mFillLineSymbol->hasDataDefinedProperties() )
3170 if ( !mRenderUsingLines )
3174 mRenderUsingLines = !applyPattern( context,
mBrush, mLineAngle, mDistance );
3177 if ( mRenderUsingLines && mFillLineSymbol )
3180 mFillLineSymbolRenderStarted =
true;
3186 if ( mFillLineSymbolRenderStarted )
3189 mFillLineSymbolRenderStarted =
false;
3196 if ( !useSelectedColor && !mRenderUsingLines )
3203 if ( !mFillLineSymbolRenderStarted && mFillLineSymbol )
3206 mFillLineSymbolRenderStarted =
true;
3236 outputPixelOffset = std::fmod( outputPixelOffset, outputPixelDistance );
3237 if ( outputPixelOffset > outputPixelDistance / 2.0 )
3238 outputPixelOffset -= outputPixelDistance;
3240 p->setPen( QPen( Qt::NoPen ) );
3262 std::unique_ptr< QgsPolygon > shapePolygon;
3263 std::unique_ptr< QgsGeometryEngine > shapeEngine;
3271 shapePolygon = std::make_unique< QgsPolygon >();
3275 for (
const QPolygonF &ring : *rings )
3281 shapeEngine->prepareGeometry();
3288 path.addPolygon( points );
3291 for (
const QPolygonF &ring : *rings )
3293 path.addPolygon( ring );
3296 p->setClipPath( path, Qt::IntersectClip );
3302 const QRectF boundingRect = points.boundingRect();
3304 QTransform invertedRotateTransform;
3310 QTransform transform;
3311 if ( applyBrushTransform )
3314 transform.translate( -boundingRect.center().x(),
3315 -boundingRect.center().y() );
3317 transform.translate( boundingRect.center().x(),
3318 boundingRect.center().y() );
3326 const QRectF transformedBounds = transform.map( points ).boundingRect();
3330 left = transformedBounds.left() - buffer * 2;
3331 top = transformedBounds.top() - buffer * 2;
3332 right = transformedBounds.right() + buffer * 2;
3333 bottom = transformedBounds.bottom() + buffer * 2;
3334 invertedRotateTransform = transform.inverted();
3336 if ( !applyBrushTransform )
3338 top -= transformedBounds.top() - ( outputPixelDistance * std::floor( transformedBounds.top() / outputPixelDistance ) );
3343 const bool needsExpressionContext = mFillLineSymbol->hasDataDefinedProperties();
3348 int currentLine = 0;
3349 for (
double currentY = top; currentY <= bottom; currentY += outputPixelDistance )
3354 if ( needsExpressionContext )
3358 double y1 = currentY;
3360 double y2 = currentY;
3361 invertedRotateTransform.map( left, currentY - outputPixelOffset, &x1, &y1 );
3362 invertedRotateTransform.map( right, currentY - outputPixelOffset, &x2, &y2 );
3367 std::unique_ptr< QgsAbstractGeometry > intersection( shapeEngine->intersection( &ls ) );
3368 for (
auto it = intersection->const_parts_begin(); it != intersection->const_parts_end(); ++it )
3370 if (
const QgsLineString *ls = qgsgeometry_cast< const QgsLineString * >( *it ) )
3378 mFillLineSymbol->renderPolyline( QPolygonF() << QPointF( x1, y1 ) << QPointF( x2, y2 ), context.
feature(), context.
renderContext(), -1, useSelectedColor );
3390 map.insert( QStringLiteral(
"angle" ), QString::number( mLineAngle ) );
3391 map.insert( QStringLiteral(
"distance" ), QString::number( mDistance ) );
3392 map.insert( QStringLiteral(
"line_width" ), QString::number( mLineWidth ) );
3394 map.insert( QStringLiteral(
"offset" ), QString::number( mOffset ) );
3410 if ( mFillLineSymbol )
3421 QDomElement symbolizerElem = doc.createElement( QStringLiteral(
"se:PolygonSymbolizer" ) );
3422 if ( !props.value( QStringLiteral(
"uom" ), QString() ).toString().isEmpty() )
3423 symbolizerElem.setAttribute( QStringLiteral(
"uom" ), props.value( QStringLiteral(
"uom" ), QString() ).toString() );
3424 element.appendChild( symbolizerElem );
3429 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
3430 symbolizerElem.appendChild( fillElem );
3432 QDomElement graphicFillElem = doc.createElement( QStringLiteral(
"se:GraphicFill" ) );
3433 fillElem.appendChild( graphicFillElem );
3435 QDomElement graphicElem = doc.createElement( QStringLiteral(
"se:Graphic" ) );
3436 graphicFillElem.appendChild( graphicElem );
3441 bool exportOk {
false };
3445 if ( ! image.isNull() )
3447 const QFileInfo info { context.exportFilePath() };
3448 QString pngPath { info.completeSuffix().isEmpty() ? context.exportFilePath() : context.exportFilePath().chopped( info.completeSuffix().length() ).append( QStringLiteral(
"png" ) ) };
3450 image.save( pngPath );
3459 QColor lineColor = mFillLineSymbol ? mFillLineSymbol->color() : QColor();
3460 double lineWidth = mFillLineSymbol ? mFillLineSymbol->width() : 0.0;
3468 double angle = props.value( QStringLiteral(
"angle" ), QStringLiteral(
"0" ) ).toDouble( &ok );
3471 angleFunc = QStringLiteral(
"%1 + %2" ).arg( props.value( QStringLiteral(
"angle" ), QStringLiteral(
"0" ) ).toString() ).arg( mLineAngle );
3475 angleFunc = QString::number(
angle + mLineAngle );
3480 QPointF lineOffset( std::sin( mLineAngle ) * mOffset, std::cos( mLineAngle ) * mOffset );
3488 QString featureStyle;
3489 featureStyle.append(
"Brush(" );
3490 featureStyle.append( QStringLiteral(
"fc:%1" ).arg(
mColor.name() ) );
3491 featureStyle.append( QStringLiteral(
",bc:%1" ).arg( QLatin1String(
"#00000000" ) ) );
3492 featureStyle.append(
",id:\"ogr-brush-2\"" );
3493 featureStyle.append( QStringLiteral(
",a:%1" ).arg( mLineAngle ) );
3494 featureStyle.append( QStringLiteral(
",s:%1" ).arg( mLineWidth * widthScaleFactor ) );
3495 featureStyle.append(
",dx:0mm" );
3496 featureStyle.append( QStringLiteral(
",dy:%1mm" ).arg( mDistance * widthScaleFactor ) );
3497 featureStyle.append(
')' );
3498 return featureStyle;
3504 && ( !mFillLineSymbol || !mFillLineSymbol->hasDataDefinedProperties() ) )
3529 Qt::PenStyle lineStyle;
3531 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
3532 if ( fillElem.isNull() )
3535 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
3536 if ( graphicFillElem.isNull() )
3539 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
3540 if ( graphicElem.isNull() )
3546 if ( name != QLatin1String(
"horline" ) )
3554 double d = angleFunc.toDouble( &ok );
3563 offset = std::sqrt( std::pow( vectOffset.x(), 2 ) + std::pow( vectOffset.y(), 2 ) );
3566 double scaleFactor = 1.0;
3567 const QString uom = element.attribute( QStringLiteral(
"uom" ) );
3569 size = size * scaleFactor;
3572 std::unique_ptr< QgsLinePatternFillSymbolLayer > sl = std::make_unique< QgsLinePatternFillSymbolLayer >();
3573 sl->setOutputUnit( sldUnitSize );
3574 sl->setColor( lineColor );
3576 sl->setLineAngle(
angle );
3578 sl->setDistance( size );
3581 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
3582 if ( !strokeElem.isNull() )
3593 return sl.release();
3693 std::unique_ptr< QgsPointPatternFillSymbolLayer > layer = std::make_unique< QgsPointPatternFillSymbolLayer >();
3694 if (
properties.contains( QStringLiteral(
"distance_x" ) ) )
3696 layer->setDistanceX(
properties[QStringLiteral(
"distance_x" )].toDouble() );
3698 if (
properties.contains( QStringLiteral(
"distance_y" ) ) )
3700 layer->setDistanceY(
properties[QStringLiteral(
"distance_y" )].toDouble() );
3702 if (
properties.contains( QStringLiteral(
"displacement_x" ) ) )
3704 layer->setDisplacementX(
properties[QStringLiteral(
"displacement_x" )].toDouble() );
3706 if (
properties.contains( QStringLiteral(
"displacement_y" ) ) )
3708 layer->setDisplacementY(
properties[QStringLiteral(
"displacement_y" )].toDouble() );
3710 if (
properties.contains( QStringLiteral(
"offset_x" ) ) )
3712 layer->setOffsetX(
properties[QStringLiteral(
"offset_x" )].toDouble() );
3714 if (
properties.contains( QStringLiteral(
"offset_y" ) ) )
3716 layer->setOffsetY(
properties[QStringLiteral(
"offset_y" )].toDouble() );
3719 if (
properties.contains( QStringLiteral(
"distance_x_unit" ) ) )
3723 if (
properties.contains( QStringLiteral(
"distance_x_map_unit_scale" ) ) )
3727 if (
properties.contains( QStringLiteral(
"distance_y_unit" ) ) )
3731 if (
properties.contains( QStringLiteral(
"distance_y_map_unit_scale" ) ) )
3735 if (
properties.contains( QStringLiteral(
"displacement_x_unit" ) ) )
3739 if (
properties.contains( QStringLiteral(
"displacement_x_map_unit_scale" ) ) )
3743 if (
properties.contains( QStringLiteral(
"displacement_y_unit" ) ) )
3747 if (
properties.contains( QStringLiteral(
"displacement_y_map_unit_scale" ) ) )
3751 if (
properties.contains( QStringLiteral(
"offset_x_unit" ) ) )
3755 if (
properties.contains( QStringLiteral(
"offset_x_map_unit_scale" ) ) )
3759 if (
properties.contains( QStringLiteral(
"offset_y_unit" ) ) )
3763 if (
properties.contains( QStringLiteral(
"offset_y_map_unit_scale" ) ) )
3768 if (
properties.contains( QStringLiteral(
"random_deviation_x" ) ) )
3770 layer->setMaximumRandomDeviationX(
properties[QStringLiteral(
"random_deviation_x" )].toDouble() );
3772 if (
properties.contains( QStringLiteral(
"random_deviation_y" ) ) )
3774 layer->setMaximumRandomDeviationY(
properties[QStringLiteral(
"random_deviation_y" )].toDouble() );
3776 if (
properties.contains( QStringLiteral(
"random_deviation_x_unit" ) ) )
3780 if (
properties.contains( QStringLiteral(
"random_deviation_x_map_unit_scale" ) ) )
3784 if (
properties.contains( QStringLiteral(
"random_deviation_y_unit" ) ) )
3788 if (
properties.contains( QStringLiteral(
"random_deviation_y_map_unit_scale" ) ) )
3792 unsigned long seed = 0;
3793 if (
properties.contains( QStringLiteral(
"seed" ) ) )
3799 std::random_device rd;
3800 std::mt19937 mt(
seed == 0 ? rd() :
seed );
3801 std::uniform_int_distribution<> uniformDist( 1, 999999999 );
3802 seed = uniformDist( mt );
3804 layer->setSeed(
seed );
3806 if (
properties.contains( QStringLiteral(
"outline_width_unit" ) ) )
3810 if (
properties.contains( QStringLiteral(
"outline_width_map_unit_scale" ) ) )
3814 if (
properties.contains( QStringLiteral(
"clip_mode" ) ) )
3818 if (
properties.contains( QStringLiteral(
"coordinate_reference" ) ) )
3823 if (
properties.contains( QStringLiteral(
"angle" ) ) )
3825 layer->setAngle(
properties[QStringLiteral(
"angle" )].toDouble() );
3828 layer->restoreOldDataDefinedProperties(
properties );
3830 return layer.release();
3835 return QStringLiteral(
"PointPatternFill" );
3838bool QgsPointPatternFillSymbolLayer::applyPattern(
const QgsSymbolRenderContext &context, QBrush &brush,
double distanceX,
double distanceY,
3839 double displacementX,
double displacementY,
double offsetX,
double offsetY )
3846 double widthOffset = std::fmod(
3849 double heightOffset = std::fmod(
3853 if ( width > 2000 || height > 2000 )
3855 brush.setTextureImage( QImage() );
3859 QImage patternImage( width, height, QImage::Format_ARGB32 );
3860 patternImage.fill( 0 );
3861 if ( patternImage.isNull() )
3863 brush.setTextureImage( QImage() );
3868 QPainter p( &patternImage );
3886 for (
double currentX = -width; currentX <= width * 2.0; currentX += width )
3888 for (
double currentY = -height; currentY <= height * 2.0; currentY += height )
3890 mMarkerSymbol->renderPoint( QPointF( currentX + widthOffset, currentY + heightOffset ), context.
feature(), pointRenderContext );
3901 for (
double currentX = -width; currentX <= width * 2.0; currentX += width )
3903 for (
double currentY = -height / 2.0; currentY <= height * 2.0; currentY += height )
3905 mMarkerSymbol->renderPoint( QPointF( currentX + widthOffset + displacementPixelX, currentY + heightOffset ), context.
feature(), pointRenderContext );
3909 for (
double currentX = -width / 2.0; currentX <= width * 2.0; currentX += width )
3911 for (
double currentY = -height; currentY <= height * 2.0; currentY += height / 2.0 )
3913 mMarkerSymbol->renderPoint( QPointF( currentX + widthOffset + ( std::fmod( currentY, height ) != 0 ? displacementPixelX : 0 ), currentY + heightOffset - displacementPixelY ), context.feature(), pointRenderContext );
3922 QImage transparentImage = patternImage.copy();
3924 brush.setTextureImage( transparentImage );
3928 brush.setTextureImage( patternImage );
3930 QTransform brushTransform;
3931 brush.setTransform( brushTransform );
3951 if ( !mRenderUsingMarkers )
3995 if ( !useSelectedColor && !mRenderUsingMarkers )
4044 const double widthOffset = std::fmod(
4056 const double heightOffset = std::fmod(
4082 p->setPen( QPen( Qt::NoPen ) );
4104 std::unique_ptr< QgsPolygon > shapePolygon;
4105 std::unique_ptr< QgsGeometryEngine > shapeEngine;
4112 shapePolygon = std::make_unique< QgsPolygon >();
4116 for (
const QPolygonF &ring : *rings )
4122 shapeEngine->prepareGeometry();
4129 path.addPolygon( points );
4132 for (
const QPolygonF &ring : *rings )
4134 path.addPolygon( ring );
4137 p->setClipPath( path, Qt::IntersectClip );
4143 const QRectF boundingRect = points.boundingRect();
4145 QTransform invertedRotateTransform;
4153 QTransform transform;
4154 if ( applyBrushTransform )
4157 transform.translate( -boundingRect.center().x(),
4158 -boundingRect.center().y() );
4159 transform.rotate( -
angle );
4160 transform.translate( boundingRect.center().x(),
4161 boundingRect.center().y() );
4166 transform.rotate( -
angle );
4169 const QRectF transformedBounds = transform.map( points ).boundingRect();
4170 left = transformedBounds.left() - 2 * width;
4171 top = transformedBounds.top() - 2 * height;
4172 right = transformedBounds.right() + 2 * width;
4173 bottom = transformedBounds.bottom() + 2 * height;
4174 invertedRotateTransform = transform.inverted();
4176 if ( !applyBrushTransform )
4178 left -= transformedBounds.left() - ( width * std::floor( transformedBounds.left() / width ) );
4179 top -= transformedBounds.top() - ( height * std::floor( transformedBounds.top() / height ) );
4184 left = boundingRect.left() - 2 * width;
4185 top = boundingRect.top() - 2 * height;
4186 right = boundingRect.right() + 2 * width;
4187 bottom = boundingRect.bottom() + 2 * height;
4189 if ( !applyBrushTransform )
4191 left -= boundingRect.left() - ( width * std::floor( boundingRect.left() / width ) );
4192 top -= boundingRect.top() - ( height * std::floor( boundingRect.top() / height ) );
4221 std::random_device rd;
4222 std::mt19937 mt(
seed == 0 ? rd() :
seed );
4223 std::uniform_real_distribution<> uniformDist( 0, 1 );
4229 const bool needsExpressionContext =
mMarkerSymbol->hasDataDefinedProperties();
4237 bool alternateColumn =
false;
4238 int currentCol = -3;
4239 for (
double currentX = left; currentX <= right; currentX += width, alternateColumn = !alternateColumn )
4244 if ( needsExpressionContext )
4247 bool alternateRow =
false;
4248 const double columnX = currentX + widthOffset;
4249 int currentRow = -3;
4250 for (
double currentY = top; currentY <= bottom; currentY += height, alternateRow = !alternateRow )
4255 double y = currentY + heightOffset;
4258 x += displacementPixelX;
4260 if ( !alternateColumn )
4261 y -= displacementPixelY;
4267 invertedRotateTransform.map( xx, yy, &x, &y );
4270 if ( useRandomShift )
4272 x += ( 2 * uniformDist( mt ) - 1 ) * maxRandomDeviationPixelX;
4273 y += ( 2 * uniformDist( mt ) - 1 ) * maxRandomDeviationPixelY;
4276 if ( needsExpressionContext )
4284 bool renderPoint =
true;
4292 renderPoint = shapeEngine->intersects( &p );
4304 renderPoint = shapeEngine->intersects( markerBounds.
constGet() );
4330 map.insert( QStringLiteral(
"distance_x" ), QString::number(
mDistanceX ) );
4331 map.insert( QStringLiteral(
"distance_y" ), QString::number(
mDistanceY ) );
4332 map.insert( QStringLiteral(
"displacement_x" ), QString::number(
mDisplacementX ) );
4333 map.insert( QStringLiteral(
"displacement_y" ), QString::number(
mDisplacementY ) );
4334 map.insert( QStringLiteral(
"offset_x" ), QString::number(
mOffsetX ) );
4335 map.insert( QStringLiteral(
"offset_y" ), QString::number(
mOffsetY ) );
4351 map.insert( QStringLiteral(
"random_deviation_x" ), QString::number(
mRandomDeviationX ) );
4352 map.insert( QStringLiteral(
"random_deviation_y" ), QString::number(
mRandomDeviationY ) );
4357 map.insert( QStringLiteral(
"seed" ), QString::number(
mSeed ) );
4358 map.insert( QStringLiteral(
"angle" ),
mAngle );
4377 for (
int symbolLayerIdx = 0; symbolLayerIdx <
mMarkerSymbol->symbolLayerCount(); symbolLayerIdx++ )
4379 QDomElement symbolizerElem = doc.createElement( QStringLiteral(
"se:PolygonSymbolizer" ) );
4380 if ( !props.value( QStringLiteral(
"uom" ), QString() ).toString().isEmpty() )
4381 symbolizerElem.setAttribute( QStringLiteral(
"uom" ), props.value( QStringLiteral(
"uom" ), QString() ).toString() );
4382 element.appendChild( symbolizerElem );
4387 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
4388 symbolizerElem.appendChild( fillElem );
4390 QDomElement graphicFillElem = doc.createElement( QStringLiteral(
"se:GraphicFill" ) );
4391 fillElem.appendChild( graphicFillElem );
4398 bool exportOk {
false };
4402 if ( ! image.isNull() )
4404 QDomElement graphicElem = doc.createElement( QStringLiteral(
"se:Graphic" ) );
4405 graphicFillElem.appendChild( graphicElem );
4406 const QFileInfo info { context.exportFilePath() };
4407 QString pngPath { info.completeSuffix().isEmpty() ? context.exportFilePath() : context.exportFilePath().chopped( info.completeSuffix().length() ).append( QStringLiteral(
"png" ) ) };
4409 image.save( pngPath );
4428 symbolizerElem.appendChild( graphicMarginElem );
4432 markerLayer->writeSldMarker( doc, graphicFillElem, props );
4436 QString errorMsg = QStringLiteral(
"QgsMarkerSymbolLayer expected, %1 found. Skip it." ).arg( layer->
layerType() );
4437 graphicFillElem.appendChild( doc.createComment( errorMsg ) );
4441 QString errorMsg = QStringLiteral(
"Missing point pattern symbol layer. Skip it." );
4442 graphicFillElem.appendChild( doc.createComment( errorMsg ) );
4451 double angleRads { qDegreesToRadians(
mAngle ) };
4460 if ( displacementXPx != 0 )
4465 if ( displacementYPx != 0 )
4472 QPixmap pixmap( size );
4473 pixmap.fill( Qt::transparent );
4475 painter.begin( &pixmap );
4476 painter.setRenderHint( QPainter::Antialiasing );
4484 std::unique_ptr< QgsPointPatternFillSymbolLayer > layerClone(
clone() );
4486 layerClone->setAngle( qRadiansToDegrees( angleRads ) );
4489 layerClone->setMaximumRandomDeviationX( 0 );
4490 layerClone->setMaximumRandomDeviationY( 0 );
4492 layerClone->drawPreviewIcon( symbolContext, pixmap.size() );
4494 return pixmap.toImage();
4502 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
4503 if ( fillElem.isNull() )
4506 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
4507 if ( graphicFillElem.isNull() )
4510 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
4511 if ( graphicElem.isNull() )
4515 if ( !simpleMarkerSl )
4520 layers.append( simpleMarkerSl );
4522 std::unique_ptr< QgsMarkerSymbol > marker = std::make_unique< QgsMarkerSymbol >( layers );
4525 const double markerSize { marker->size() };
4527 std::unique_ptr< QgsPointPatternFillSymbolLayer > pointPatternFillSl = std::make_unique< QgsPointPatternFillSymbolLayer >();
4528 pointPatternFillSl->setSubSymbol( marker.release() );
4533 auto distanceParser = [ & ](
const QStringList & values )
4535 switch ( values.count( ) )
4540 const double v { values.at( 0 ).toDouble( &ok ) };
4543 pointPatternFillSl->setDistanceX( v * 2 + markerSize );
4544 pointPatternFillSl->setDistanceY( v * 2 + markerSize );
4551 const double vX { values.at( 1 ).toDouble( &ok ) };
4554 pointPatternFillSl->setDistanceX( vX * 2 + markerSize );
4556 const double vY { values.at( 0 ).toDouble( &ok ) };
4559 pointPatternFillSl->setDistanceY( vY * 2 + markerSize );
4566 const double vX { values.at( 1 ).toDouble( &ok ) };
4569 pointPatternFillSl->setDistanceX( vX * 2 + markerSize );
4571 const double vYt { values.at( 0 ).toDouble( &ok ) };
4574 const double vYb { values.at( 2 ).toDouble( &ok ) };
4577 pointPatternFillSl->setDistanceY( ( vYt + vYb ) + markerSize );
4585 const double vYt { values.at( 0 ).toDouble( &ok ) };
4588 const double vYb { values.at( 2 ).toDouble( &ok ) };
4591 pointPatternFillSl->setDistanceY( ( vYt + vYb ) + markerSize );
4594 const double vXr { values.at( 1 ).toDouble( &ok ) };
4597 const double vXl { values.at( 3 ).toDouble( &ok ) };
4600 pointPatternFillSl->setDistanceX( ( vXr + vXl ) + markerSize );
4611 bool distanceFromVendorOption {
false };
4613 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
4616 if ( it.key() == QLatin1String(
"distance" ) )
4618 distanceParser( it.value().split(
',' ) );
4619 distanceFromVendorOption =
true;
4622 else if ( it.key() == QLatin1String(
"graphic-margin" ) )
4624 distanceParser( it.value().split(
' ' ) );
4625 distanceFromVendorOption =
true;
4630 if ( ! distanceFromVendorOption && ! graphicFillElem.elementsByTagName( QStringLiteral(
"Size" ) ).isEmpty() )
4632 const QDomElement sizeElement { graphicFillElem.elementsByTagName( QStringLiteral(
"Size" ) ).at( 0 ).toElement() };
4634 const double size { sizeElement.text().toDouble( &ok ) };
4637 pointPatternFillSl->setDistanceX( size );
4638 pointPatternFillSl->setDistanceY( size );
4642 return pointPatternFillSl.release();
4724 attributes.unite(
mMarkerSymbol->usedAttributes( context ) );
4762 std::unique_ptr< QgsCentroidFillSymbolLayer > sl = std::make_unique< QgsCentroidFillSymbolLayer >();
4764 if (
properties.contains( QStringLiteral(
"point_on_surface" ) ) )
4765 sl->setPointOnSurface(
properties[QStringLiteral(
"point_on_surface" )].toInt() != 0 );
4766 if (
properties.contains( QStringLiteral(
"point_on_all_parts" ) ) )
4767 sl->setPointOnAllParts(
properties[QStringLiteral(
"point_on_all_parts" )].toInt() != 0 );
4768 if (
properties.contains( QStringLiteral(
"clip_points" ) ) )
4769 sl->setClipPoints(
properties[QStringLiteral(
"clip_points" )].toInt() != 0 );
4770 if (
properties.contains( QStringLiteral(
"clip_on_current_part_only" ) ) )
4771 sl->setClipOnCurrentPartOnly(
properties[QStringLiteral(
"clip_on_current_part_only" )].toInt() != 0 );
4773 sl->restoreOldDataDefinedProperties(
properties );
4775 return sl.release();
4780 return QStringLiteral(
"CentroidFill" );
4807 part.exterior = points;
4809 part.rings = *rings;
4817 mCurrentParts << part;
4822 const double prevOpacity =
mMarker->opacity();
4826 mMarker->setOpacity( prevOpacity );
4835 mCurrentParts.clear();
4842 const double prevOpacity =
mMarker->opacity();
4848 mMarker->setOpacity( prevOpacity );
4853void QgsCentroidFillSymbolLayer::render(
QgsRenderContext &context,
const QVector<QgsCentroidFillSymbolLayer::Part> &parts,
const QgsFeature &feature,
bool selected )
4862 QVector< QgsGeometry > geometryParts;
4863 geometryParts.reserve( parts.size() );
4864 QPainterPath globalPath;
4867 int maxAreaPartIdx = 0;
4869 for (
int i = 0; i < parts.size(); i++ )
4871 const Part part = parts[i];
4874 if ( !geom.
isNull() && !part.rings.empty() )
4876 QgsPolygon *poly = qgsgeometry_cast< QgsPolygon * >( geom.
get() );
4880 int area = poly->
area();
4882 if ( area > maxArea )
4892 globalPath.addPolygon( part.exterior );
4893 for (
const QPolygonF &ring : part.rings )
4895 globalPath.addPolygon( ring );
4900 for (
int i = 0; i < parts.size(); i++ )
4905 const Part part = parts[i];
4913 path.addPolygon( part.exterior );
4914 for (
const QPolygonF &ring : part.rings )
4916 path.addPolygon( ring );
4925 context.
painter()->setClipPath( path );
4932 mMarker->renderPoint( centroid, feature.
isValid() ? &feature : nullptr, context, -1, selected );
4945 map[QStringLiteral(
"point_on_surface" )] = QString::number(
mPointOnSurface );
4946 map[QStringLiteral(
"point_on_all_parts" )] = QString::number(
mPointOnAllParts );
4947 map[QStringLiteral(
"clip_points" )] = QString::number(
mClipPoints );
4954 std::unique_ptr< QgsCentroidFillSymbolLayer > x = std::make_unique< QgsCentroidFillSymbolLayer >();
4957 x->setSubSymbol(
mMarker->clone() );
4972 mMarker->toSld( doc, element, props );
4983 std::unique_ptr< QgsMarkerSymbol > marker(
new QgsMarkerSymbol( layers ) );
4985 std::unique_ptr< QgsCentroidFillSymbolLayer > sl = std::make_unique< QgsCentroidFillSymbolLayer >();
4986 sl->setSubSymbol( marker.release() );
4987 sl->setPointOnAllParts(
false );
4988 return sl.release();
5015 attributes.unite(
mMarker->usedAttributes( context ) );
5038 mMarker->setOutputUnit( unit );
5055 return mMarker->usesMapUnits();
5064 mMarker->setMapUnitScale( scale );
5072 return mMarker->mapUnitScale();
5082 , mImageFilePath( imageFilePath )
5099 if (
properties.contains( QStringLiteral(
"imageFile" ) ) )
5101 imagePath =
properties[QStringLiteral(
"imageFile" )].toString();
5103 if (
properties.contains( QStringLiteral(
"coordinate_mode" ) ) )
5107 if (
properties.contains( QStringLiteral(
"alpha" ) ) )
5109 alpha =
properties[QStringLiteral(
"alpha" )].toDouble();
5111 if (
properties.contains( QStringLiteral(
"offset" ) ) )
5115 if (
properties.contains( QStringLiteral(
"angle" ) ) )
5119 if (
properties.contains( QStringLiteral(
"width" ) ) )
5123 std::unique_ptr< QgsRasterFillSymbolLayer > symbolLayer = std::make_unique< QgsRasterFillSymbolLayer >( imagePath );
5124 symbolLayer->setCoordinateMode( mode );
5125 symbolLayer->setOpacity( alpha );
5126 symbolLayer->setOffset(
offset );
5127 symbolLayer->setAngle(
angle );
5128 symbolLayer->setWidth(
width );
5129 if (
properties.contains( QStringLiteral(
"offset_unit" ) ) )
5133 if (
properties.contains( QStringLiteral(
"offset_map_unit_scale" ) ) )
5137 if (
properties.contains( QStringLiteral(
"width_unit" ) ) )
5141 if (
properties.contains( QStringLiteral(
"width_map_unit_scale" ) ) )
5146 if (
properties.contains( QStringLiteral(
"height" ) ) )
5148 symbolLayer->setHeight(
properties[QStringLiteral(
"height" )].toDouble() );
5151 symbolLayer->restoreOldDataDefinedProperties(
properties );
5153 return symbolLayer.release();
5158 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
5159 if ( fillElem.isNull() )
5162 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
5163 if ( graphicFillElem.isNull() )
5166 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
5167 if ( graphicElem.isNull() )
5170 QString path, mimeType;
5178 if ( ! QFile::exists( path ) )
5183 std::unique_ptr< QgsRasterFillSymbolLayer> sl = std::make_unique< QgsRasterFillSymbolLayer>( path );
5185 return sl.release();
5190 QVariantMap::iterator it =
properties.find( QStringLiteral(
"imageFile" ) );
5194 it.value() = pathResolver.
writePath( it.value().toString() );
5196 it.value() = pathResolver.
readPath( it.value().toString() );
5208 return QStringLiteral(
"RasterFill" );
5219 QPointF
offset = mOffset;
5237 QRectF boundingRect = points.boundingRect();
5238 mBrush.setTransform(
mBrush.transform().translate( boundingRect.left() -
mBrush.transform().dx(),
5239 boundingRect.top() -
mBrush.transform().dy() ) );
5251 applyPattern(
mBrush, mImageFilePath, mWidth, mHeight, mOpacity * context.
opacity(), context );
5262 map[QStringLiteral(
"imageFile" )] = mImageFilePath;
5263 map[QStringLiteral(
"coordinate_mode" )] = QString::number(
static_cast< int >( mCoordinateMode ) );
5264 map[QStringLiteral(
"alpha" )] = QString::number( mOpacity );
5268 map[QStringLiteral(
"angle" )] = QString::number(
mAngle );
5270 map[QStringLiteral(
"width" )] = QString::number( mWidth );
5271 map[QStringLiteral(
"height" )] = QString::number( mHeight );
5280 std::unique_ptr< QgsRasterFillSymbolLayer > sl = std::make_unique< QgsRasterFillSymbolLayer >( mImageFilePath );
5281 sl->setCoordinateMode( mCoordinateMode );
5282 sl->setOpacity( mOpacity );
5283 sl->setOffset( mOffset );
5284 sl->setOffsetUnit( mOffsetUnit );
5285 sl->setOffsetMapUnitScale( mOffsetMapUnitScale );
5287 sl->setWidth( mWidth );
5288 sl->setHeight( mHeight );
5289 sl->setSizeUnit( mSizeUnit );
5290 sl->setSizeMapUnitScale( mSizeMapUnitScale );
5294 return sl.release();
5299 return context.
convertToPainterUnits( std::max( std::fabs( mOffset.x() ), std::fabs( mOffset.y() ) ), mOffsetUnit, mOffsetMapUnitScale );
5322 mImageFilePath = imagePath;
5327 mCoordinateMode = mode;
5346 if ( !hasWidthExpression && !hasHeightExpression && !hasAngleExpression && !hasOpacityExpression && !hasFileExpression )
5352 if ( hasAngleExpression )
5360 if ( !hasWidthExpression && !hasHeightExpression && !hasOpacityExpression && !hasFileExpression )
5365 double width = mWidth;
5366 if ( hasWidthExpression )
5372 if ( hasHeightExpression )
5378 if ( hasOpacityExpression )
5383 QString file = mImageFilePath;
5384 if ( hasFileExpression )
5397void QgsRasterFillSymbolLayer::applyPattern( QBrush &brush,
const QString &imageFilePath,
const double width,
const double height,
const double alpha,
const QgsSymbolRenderContext &context )
5399 double imageWidth = 0;
5400 double imageHeight = 0;
5415 if ( originalSize.isEmpty() )
5418 imageWidth = (
width * originalSize.width() ) / 100.0;
5421 if (
static_cast< int >( imageWidth ) < 1 || 10000.0 < imageWidth )
5434 if ( !originalSize.isValid() )
5437 if ( originalSize.isEmpty() )
5440 imageHeight = (
height * originalSize.height() ) / 100.0;
5443 if (
static_cast< int >( imageHeight ) < 1 || 10000.0 < imageHeight )
5448 if (
width == 0 && imageHeight > 0 )
5450 if ( !originalSize.isValid() )
5453 imageWidth = imageHeight * originalSize.width() / originalSize.height();
5455 else if (
height == 0 && imageWidth > 0 )
5457 if ( !originalSize.isValid() )
5460 imageHeight = imageWidth * originalSize.height() / originalSize.width();
5462 if ( imageWidth == 0 || imageHeight == 0 )
5464 if ( !originalSize.isValid() )
5467 imageWidth = originalSize.width();
5468 imageHeight = originalSize.height();
5476 brush.setTextureImage( img );
5485 : mCountMethod( method )
5486 , mPointCount( pointCount )
5487 , mDensityArea( densityArea )
5498 const int pointCount =
properties.value( QStringLiteral(
"point_count" ), QStringLiteral(
"10" ) ).toInt();
5499 const double densityArea =
properties.value( QStringLiteral(
"density_area" ), QStringLiteral(
"250.0" ) ).toDouble();
5501 unsigned long seed = 0;
5502 if (
properties.contains( QStringLiteral(
"seed" ) ) )
5508 std::random_device rd;
5509 std::mt19937 mt(
seed == 0 ? rd() :
seed );
5510 std::uniform_int_distribution<> uniformDist( 1, 999999999 );
5511 seed = uniformDist( mt );
5516 if (
properties.contains( QStringLiteral(
"density_area_unit" ) ) )
5518 if (
properties.contains( QStringLiteral(
"density_area_unit_scale" ) ) )
5521 if (
properties.contains( QStringLiteral(
"clip_points" ) ) )
5523 sl->setClipPoints(
properties[QStringLiteral(
"clip_points" )].toInt() );
5526 return sl.release();
5531 return QStringLiteral(
"RandomMarkerFill" );
5536 mMarker->setColor(
color );
5542 return mMarker ? mMarker->color() :
mColor;
5558 part.exterior = points;
5560 part.rings = *rings;
5562 if ( mRenderingFeature )
5566 mFeatureSymbolOpacity = context.
opacity();
5567 mCurrentParts << part;
5572 const double prevOpacity = mMarker->opacity();
5573 mMarker->setOpacity( mMarker->opacity() * context.
opacity() );
5576 mMarker->setOpacity( prevOpacity );
5580void QgsRandomMarkerFillSymbolLayer::render(
QgsRenderContext &context,
const QVector<QgsRandomMarkerFillSymbolLayer::Part> &parts,
const QgsFeature &feature,
bool selected )
5589 QVector< QgsGeometry > geometryParts;
5590 geometryParts.reserve( parts.size() );
5593 for (
const Part &part : parts )
5596 if ( !geom.
isNull() && !part.rings.empty() )
5598 QgsPolygon *poly = qgsgeometry_cast< QgsPolygon * >( geom.
get() );
5599 for (
const QPolygonF &ring : part.rings )
5606 geom = geom.
buffer( 0, 0 );
5608 geometryParts << geom;
5612 path.addPolygon( part.exterior );
5613 for (
const QPolygonF &ring : part.rings )
5615 path.addPolygon( ring );
5625 context.
painter()->setClipPath( path );
5629 int count = mPointCount;
5636 switch ( mCountMethod )
5648 count = std::max( 0.0, std::ceil( count * ( geom.
area() /
densityArea ) ) );
5655 unsigned long seed = mSeed;
5666 std::sort( randomPoints.begin(), randomPoints.end(), [](
const QgsPointXY & a,
const QgsPointXY & b )->bool
5668 return a.y() < b.y();
5674 const bool needsExpressionContext = mMarker->hasDataDefinedProperties();
5679 for (
const QgsPointXY &p : std::as_const( randomPoints ) )
5681 if ( needsExpressionContext )
5683 mMarker->renderPoint( QPointF( p.x(), p.y() ), feature.
isValid() ? &feature : nullptr, context, -1, selected );
5697 map.insert( QStringLiteral(
"count_method" ), QString::number(
static_cast< int >( mCountMethod ) ) );
5698 map.insert( QStringLiteral(
"point_count" ), QString::number( mPointCount ) );
5699 map.insert( QStringLiteral(
"density_area" ), QString::number( mDensityArea ) );
5702 map.insert( QStringLiteral(
"seed" ), QString::number( mSeed ) );
5703 map.insert( QStringLiteral(
"clip_points" ), QString::number( mClipPoints ) );
5709 std::unique_ptr< QgsRandomMarkerFillSymbolLayer > res = std::make_unique< QgsRandomMarkerFillSymbolLayer >( mPointCount, mCountMethod, mDensityArea, mSeed );
5712 res->setDensityAreaUnit( mDensityAreaUnit );
5713 res->setDensityAreaUnitScale( mDensityAreaUnitScale );
5714 res->mClipPoints = mClipPoints;
5715 res->setSubSymbol( mMarker->clone() );
5718 return res.release();
5728 return mMarker.get();
5740 mColor = mMarker->color();
5749 attributes.unite( mMarker->usedAttributes( context ) );
5758 if ( mMarker && mMarker->hasDataDefinedProperties() )
5795 return mCountMethod;
5800 mCountMethod = method;
5805 return mDensityArea;
5810 mDensityArea = area;
5817 mRenderingFeature =
true;
5818 mCurrentParts.clear();
5823 mRenderingFeature =
false;
5825 const double prevOpacity = mMarker->opacity();
5826 mMarker->setOpacity( mMarker->opacity() * mFeatureSymbolOpacity );
5828 render( context, mCurrentParts, feature,
false );
5830 mFeatureSymbolOpacity = 1;
5831 mMarker->setOpacity( prevOpacity );
5839 mDensityAreaUnit = unit;
5842 mMarker->setOutputUnit( unit );
5850 return mMarker->outputUnit();
5859 return mMarker->usesMapUnits();
5868 mMarker->setMapUnitScale( scale );
5876 return mMarker->mapUnitScale();
MarkerClipMode
Marker clipping modes.
@ CompletelyWithin
Render complete markers wherever the completely fall within the polygon shape.
@ NoClipping
No clipping, render complete markers.
@ Shape
Clip to polygon shape.
@ CentroidWithin
Render complete markers wherever their centroid falls within the polygon shape.
LineClipMode
Line clipping modes.
@ NoClipping
Lines are not clipped, will extend to shape's bounding box.
@ ClipPainterOnly
Applying clipping on the painter only (i.e. line endpoints will coincide with polygon bounding box,...
@ ClipToIntersection
Clip lines to intersection with polygon shape (slower) (i.e. line endpoints will coincide with polygo...
GradientColorSource
Gradient color sources.
@ ColorRamp
Gradient color ramp.
@ SimpleTwoColor
Simple two color gradient.
GradientSpread
Gradient spread options, which control how gradients are rendered outside of their start and end poin...
@ Reflect
Reflect gradient.
@ Pad
Pad out gradient using colors at endpoint of gradient.
@ Png
Export complex styles to separate PNG files for better compatibility with OGC servers.
PointCountMethod
Methods which define the number of points randomly filling a polygon.
@ Absolute
The point count is used as an absolute count of markers.
@ DensityBased
The point count is part of a marker density count.
RenderUnit
Rendering size units.
@ Percentage
Percentage of another measurement (e.g., canvas size, feature size)
@ Unknown
Mixed or unknown units.
@ MetersInMapUnits
Meters value as Map units.
@ RenderingSubSymbol
Set whenever a sub-symbol of a parent symbol is currently being rendered. Can be used during symbol a...
@ RenderSymbolPreview
The render is for a symbol preview only and map based properties may not be available,...
@ RenderMapTile
Draw map such that there are no problems between adjacent tiles.
@ HighQualityImageTransforms
Enable high quality image transformations, which results in better appearance of scaled or rotated ra...
@ RenderBlocking
Render and load remote sources in the same thread to ensure rendering remote sources (svg and images)...
GradientType
Gradient types.
@ Conical
Conical (polar) gradient.
@ Radial
Radial (circular) gradient.
QFlags< SymbolRenderHint > SymbolRenderHints
Symbol render hints.
SymbolCoordinateReference
Symbol coordinate reference modes.
@ Feature
Relative to feature/shape being rendered.
@ Viewport
Relative to the whole viewport/output device.
QColor valueAsColor(int key, const QgsExpressionContext &context, const QColor &defaultColor=QColor(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a color.
int valueAsInt(int key, const QgsExpressionContext &context, int defaultValue=0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as an integer.
bool valueAsBool(int key, const QgsExpressionContext &context, bool defaultValue=false, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as an boolean.
double valueAsDouble(int key, const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a double.
QString valueAsString(int key, const QgsExpressionContext &context, const QString &defaultString=QString(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a string.
static QgsImageCache * imageCache()
Returns the application's image cache, used for caching resampled versions of raster images.
static QgsSvgCache * svgCache()
Returns the application's SVG cache, used for caching SVG images and handling parameter replacement w...
static QgsSymbolLayer * createFromSld(QDomElement &element)
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
void setMapUnitScale(const QgsMapUnitScale &scale) override
bool canCauseArtifactsBetweenAdjacentTiles() const override
Returns true if the symbol layer rendering can cause visible artifacts across a single feature when t...
bool pointOnSurface() const
QgsMapUnitScale mapUnitScale() const override
void startFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called before the layer will be rendered for a particular feature.
std::unique_ptr< QgsMarkerSymbol > mMarker
QString layerType() const override
Returns a string that represents this layer type.
void setColor(const QColor &color) override
Sets the "representative" color for the symbol layer.
bool pointOnAllParts() const
Returns whether a point is drawn for all parts or only on the biggest part of multi-part features.
void renderPolygon(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context) override
Renders the fill symbol layer for the polygon whose outer ring is defined by points,...
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
bool setSubSymbol(QgsSymbol *symbol) FINAL
Sets layer's subsymbol. takes ownership of the passed symbol.
void stopFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called after the layer has been rendered for a particular feature.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
bool clipPoints() const
Returns true if point markers should be clipped to the polygon boundary.
QgsCentroidFillSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props) const override
Saves the symbol layer as SLD.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsCentroidFillSymbolLayer using the specified properties map containing symbol propert...
~QgsCentroidFillSymbolLayer() override
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
double mFeatureSymbolOpacity
QgsCentroidFillSymbolLayer()
QColor color() const override
Returns the "representative" color of the symbol layer.
bool clipOnCurrentPartOnly() const
Returns true if point markers should be clipped to the current part boundary only.
bool mClipOnCurrentPartOnly
Abstract base class for color ramps.
virtual QColor color(double value) const =0
Returns the color corresponding to a specified value.
virtual QVariantMap properties() const =0
Returns a string map containing all the color ramp's properties.
virtual QgsColorRamp * clone() const =0
Creates a clone of the color ramp.
virtual QString type() const =0
Returns a string representing the color ramp type.
static QColor colorFromString(const QString &string)
Decodes a string into a color value.
static QString colorToString(const QColor &color)
Encodes a color into a string value.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates the symbol layer.
static QString typeString()
Returns the string identifier for QgsCptCityColorRamp.
double area() const override
Returns the planar, 2-dimensional area of the geometry.
Exports QGIS layers to the DXF format.
static double mapUnitScaleFactor(double scale, Qgis::RenderUnit symbolUnits, Qgis::DistanceUnit mapUnits, double mapUnitsPerPixel=1.0)
Returns scale factor for conversion to map units.
Qgis::DistanceUnit mapUnits() const
Retrieve map units.
double symbologyScale() const
Returns the reference scale for output.
RAII class to pop scope from an expression context on destruction.
Single scope for storing variables and functions for use within a QgsExpressionContext.
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
static const QString EXPR_GEOMETRY_POINT_NUM
Inbuilt variable name for point number variable.
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for the context.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool isValid() const
Returns the validity of this feature.
bool isCanceled() const
Tells whether the operation has been canceled already.
static QString uniquePath(const QString &path)
Creates a unique file path name from a desired path by appending "_<n>" (where "<n>" is an integer nu...
void _renderPolygon(QPainter *p, const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context)
Default method to render polygon.
double angle() const
Returns the rotation angle of the fill symbol, in degrees clockwise.
A geometry is the spatial representation of a feature.
QVector< QgsPointXY > randomPointsInPolygon(int count, const std::function< bool(const QgsPointXY &) > &acceptPoint, unsigned long seed=0, QgsFeedback *feedback=nullptr, int maxTriesPerPoint=0) const
Returns a list of count random points generated inside a (multi)polygon geometry (if acceptPoint is s...
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
static QgsGeometry fromQPolygonF(const QPolygonF &polygon)
Construct geometry from a QPolygonF.
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
bool contains(const QgsPointXY *p) const
Returns true if the geometry contains the point p.
bool isGeosValid(Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const
Checks validity of the geometry using GEOS.
double area() const
Returns the planar, 2-dimensional area of the geometry.
QgsGeometry buffer(double distance, int segments) const
Returns a buffer region around this geometry having the given width and with a specified number of se...
static QgsGeometry unaryUnion(const QVector< QgsGeometry > &geometries, const QgsGeometryParameters ¶meters=QgsGeometryParameters())
Compute the unary union on a list of geometries.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsColorRamp from a map of properties.
static QString typeString()
Returns the string identifier for QgsGradientColorRamp.
void addStopsToGradient(QGradient *gradient, double opacity=1) const
Copy color ramp stops to a QGradient.
void setColorRamp(QgsColorRamp *ramp)
Sets the color ramp used for the gradient fill.
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
QColor color2() const
Returns the color for endpoint of gradient, only used if the gradient color type is set to SimpleTwoC...
void renderPolygon(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context) override
Renders the fill symbol layer for the polygon whose outer ring is defined by points,...
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
bool canCauseArtifactsBetweenAdjacentTiles() const override
Returns true if the symbol layer rendering can cause visible artifacts across a single feature when t...
QgsGradientFillSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
QgsMapUnitScale mapUnitScale() const override
bool mReferencePoint1IsCentroid
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
Qgis::SymbolCoordinateReference coordinateMode() const
Returns the coordinate mode for gradient, which controls how the gradient stops are positioned.
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
Qgis::SymbolCoordinateReference mCoordinateMode
QgsGradientFillSymbolLayer(const QColor &color=DEFAULT_SIMPLEFILL_COLOR, const QColor &color2=Qt::white, Qgis::GradientColorSource gradientColorType=Qgis::GradientColorSource::SimpleTwoColor, Qgis::GradientType gradientType=Qgis::GradientType::Linear, Qgis::SymbolCoordinateReference coordinateMode=Qgis::SymbolCoordinateReference::Feature, Qgis::GradientSpread gradientSpread=Qgis::GradientSpread::Pad)
Constructor for QgsGradientFillSymbolLayer.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsGradientFillSymbolLayer using the specified properties map containing symbol propert...
void setMapUnitScale(const QgsMapUnitScale &scale) override
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
Qgis::GradientSpread mGradientSpread
~QgsGradientFillSymbolLayer() override
Qgis::GradientType mGradientType
QgsColorRamp * mGradientRamp
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
QPointF referencePoint1() const
Returns the starting point of gradient fill, in the range [0,0] - [1,1].
Qgis::GradientSpread gradientSpread() const
Returns the gradient spread mode, which controls how the gradient behaves outside of the predefined s...
bool mReferencePoint2IsCentroid
QgsMapUnitScale mOffsetMapUnitScale
Qgis::GradientColorSource gradientColorType() const
Returns the gradient color mode, which controls how gradient color stops are created.
QPointF offset() const
Returns the offset by which polygons will be translated during rendering.
Qgis::GradientColorSource mGradientColorType
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
QString layerType() const override
Returns a string that represents this layer type.
Qgis::RenderUnit mOffsetUnit
Qgis::GradientType gradientType() const
Returns the type of gradient, e.g., linear or radial.
QPointF referencePoint2() const
Returns the end point of gradient fill, in the range [0,0] - [1,1].
QSize originalSize(const QString &path, bool blocking=false) const
Returns the original size (in pixels) of the image at the specified path.
QImage pathAsImage(const QString &path, const QSize size, const bool keepAspectRatio, const double opacity, bool &fitsInCache, bool blocking=false, double targetDpi=96, int frameNumber=-1, bool *isMissing=nullptr)
Returns the specified path rendered as an image.
Base class for polygon renderers generating texture images.
QgsMapUnitScale mStrokeWidthMapUnitScale
QgsImageFillSymbolLayer()
Qgis::SymbolCoordinateReference coordinateReference() const
Returns the coordinate reference mode for fill which controls how the top left corner of the image fi...
double mStrokeWidth
Stroke width.
Qgis::SymbolCoordinateReference mCoordinateReference
double dxfWidth(const QgsDxfExport &e, QgsSymbolRenderContext &context) const override
Gets line width.
QgsMapUnitScale mapUnitScale() const override
Qt::PenStyle dxfPenStyle() const override
Gets pen style.
Qgis::RenderUnit mStrokeWidthUnit
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
void setMapUnitScale(const QgsMapUnitScale &scale) override
virtual void applyDataDefinedSettings(QgsSymbolRenderContext &context)
Applies data defined settings prior to generating the fill symbol brush.
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
void renderPolygon(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context) override
Renders the fill symbol layer for the polygon whose outer ring is defined by points,...
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
~QgsImageFillSymbolLayer() override
virtual bool applyBrushTransformFromContext(QgsSymbolRenderContext *context=nullptr) const
Returns true if the image brush should be transformed using the render context's texture origin.
static void multiplyOpacity(QImage &image, double factor, QgsFeedback *feedback=nullptr)
Multiplies opacity of image pixel values by a factor.
static void stackBlur(QImage &image, int radius, bool alphaOnly=false, QgsFeedback *feedback=nullptr)
Performs a stack blur on an image.
A symbol fill consisting of repeated parallel lines.
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
QgsMapUnitScale mapUnitScale() const override
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
QString layerType() const override
Returns a string that represents this layer type.
QgsLinePatternFillSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
void stopFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called after the layer has been rendered for a particular feature.
void startFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called before the layer will be rendered for a particular feature.
QColor color() const override
Returns the "representative" color of the symbol layer.
void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props) const override
Saves the symbol layer as SLD.
double lineWidth() const
Returns the width of the line subsymbol used to render the parallel lines in the fill.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
void setMapUnitScale(const QgsMapUnitScale &scale) override
Qgis::LineClipMode clipMode() const
Returns the line clipping mode, which defines how lines are clipped at the edges of shapes.
double lineAngle() const
Returns the angle for the parallel lines used to fill the symbol.
void setLineWidth(double w)
Sets the width of the line subsymbol used to render the parallel lines in the fill.
void renderPolygon(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context) override
Renders the fill symbol layer for the polygon whose outer ring is defined by points,...
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
void applyDataDefinedSettings(QgsSymbolRenderContext &context) override
Applies data defined settings prior to generating the fill symbol brush.
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void setColor(const QColor &c) override
Sets the "representative" color for the symbol layer.
QImage toTiledPatternImage() const override
Renders the symbol layer as an image that can be used as a seamless pattern fill for polygons,...
double offset() const
Returns the offset distance for lines within the fill, which is the distance to offset the parallel l...
QgsLinePatternFillSymbolLayer()
double distance() const
Returns the distance between lines in the fill pattern.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
QString ogrFeatureStyleWidth(double widthScaleFactor) const
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
~QgsLinePatternFillSymbolLayer() override
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
static QgsSymbolLayer * createFromSld(QDomElement &element)
Creates a new QgsLinePatternFillSymbolLayer from a SLD element.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsLinePatternFillSymbolLayer from a properties map.
Line string geometry type, with support for z-dimension and m-values.
QPolygonF asQPolygonF() const override
Returns a QPolygonF representing the points.
static QgsLineString * fromQPolygonF(const QPolygonF &polygon)
Returns a new linestring from a QPolygonF polygon input.
A line symbol type, for rendering LineString and MultiLineString geometries.
Perform transforms between map coordinates and device coordinates.
double mapUnitsPerPixel() const
Returns the current map units per pixel.
Struct for storing maximum and minimum scales for measurements in map units.
Line symbol layer type which draws repeating marker symbols along a line feature.
Abstract base class for marker symbol layers.
A marker symbol type, for rendering Point and MultiPoint geometries.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Resolves relative paths into absolute paths and vice versa.
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
A fill symbol layer which fills polygon shapes with repeating marker symbols.
QgsMapUnitScale mapUnitScale() const override
QgsMapUnitScale mDisplacementYMapUnitScale
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
QgsMapUnitScale mDisplacementXMapUnitScale
void renderPolygon(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context) override
Renders the fill symbol layer for the polygon whose outer ring is defined by points,...
double distanceX() const
Returns the horizontal distance between rendered markers in the fill.
QgsMapUnitScale mDistanceYMapUnitScale
QImage toTiledPatternImage() const override
Renders the symbol layer as an image that can be used as a seamless pattern fill for polygons,...
double displacementY() const
Returns the vertical displacement for odd numbered columns in the pattern.
void setColor(const QColor &c) override
Sets the "representative" color for the symbol layer.
Qgis::RenderUnit mDistanceXUnit
void startFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called before the layer will be rendered for a particular feature.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsPointPatternFillSymbolLayer using the specified properties map containing symbol pro...
unsigned long seed() const
Returns the random number seed to use when randomly shifting points, or 0 if a truly random sequence ...
Qgis::RenderUnit mDisplacementYUnit
Qgis::MarkerClipMode clipMode() const
Returns the marker clipping mode, which defines how markers are clipped at the edges of shapes.
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
double offsetY() const
Returns the vertical offset values for points in the pattern.
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
QgsMapUnitScale mDistanceXMapUnitScale
void setMapUnitScale(const QgsMapUnitScale &scale) override
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
QString layerType() const override
Returns a string that represents this layer type.
void applyDataDefinedSettings(QgsSymbolRenderContext &context) override
Applies data defined settings prior to generating the fill symbol brush.
Qgis::RenderUnit mRandomDeviationXUnit
Qgis::RenderUnit mOffsetXUnit
Qgis::RenderUnit mDistanceYUnit
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
QgsMapUnitScale mOffsetXMapUnitScale
void stopFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called after the layer has been rendered for a particular feature.
Qgis::RenderUnit mOffsetYUnit
QColor color() const override
Returns the "representative" color of the symbol layer.
Qgis::RenderUnit mRandomDeviationYUnit
QgsPointPatternFillSymbolLayer()
QgsMapUnitScale mRandomDeviationXMapUnitScale
void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props) const override
Saves the symbol layer as SLD.
double offsetX() const
Returns the horizontal offset values for points in the pattern.
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
Qgis::RenderUnit mDisplacementXUnit
std::unique_ptr< QgsMarkerSymbol > mMarkerSymbol
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
QgsPointPatternFillSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
QgsMapUnitScale mRandomDeviationYMapUnitScale
double displacementX() const
Returns the horizontal displacement for odd numbered rows in the pattern.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
~QgsPointPatternFillSymbolLayer() override
QgsMapUnitScale mOffsetYMapUnitScale
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
double distanceY() const
Returns the vertical distance between rendered markers in the fill.
void setClipMode(Qgis::MarkerClipMode mode)
Sets the marker clipping mode, which defines how markers are clipped at the edges of shapes.
static QgsSymbolLayer * createFromSld(QDomElement &element)
bool mMarkerSymbolRenderStarted
A class to represent a 2D point.
Point geometry type, with support for z-dimension and m-values.
void addInteriorRing(QgsCurve *ring) override
Adds an interior ring to the geometry (takes ownership)
static QgsProject * instance()
Returns the QgsProject singleton instance.
QgsPathResolver pathResolver() const
Returns path resolver object with considering whether the project uses absolute or relative paths and...
QVariant value(int key, const QgsExpressionContext &context, const QVariant &defaultValue=QVariant()) const final
Returns the calculated value of the property with the specified key from within the collection.
bool isActive(int key) const final
Returns true if the collection contains an active property with the specified key.
static QVariantMap propertyMapToVariantMap(const QMap< QString, QgsProperty > &propertyMap)
Convert a map of QgsProperty to a map of QVariant This is useful to save a map of properties.
static QMap< QString, QgsProperty > variantMapToPropertyMap(const QVariantMap &variantMap)
Convert a map of QVariant to a map of QgsProperty This is useful to restore a map of properties.
A fill symbol layer which places markers at random locations within polygons.
~QgsRandomMarkerFillSymbolLayer() override
int pointCount() const
Returns the count of random points to render in the fill.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
void startFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called before the layer will be rendered for a particular feature.
QgsRandomMarkerFillSymbolLayer(int pointCount=10, Qgis::PointCountMethod method=Qgis::PointCountMethod::Absolute, double densityArea=250.0, unsigned long seed=0)
Constructor for QgsRandomMarkerFillSymbolLayer, with the specified pointCount.
unsigned long seed() const
Returns the random number seed to use when generating points, or 0 if a truly random sequence will be...
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsRandomMarkerFillSymbolLayer using the specified properties map containing symbol pro...
void renderPolygon(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context) override
Renders the fill symbol layer for the polygon whose outer ring is defined by points,...
QString layerType() const override
Returns a string that represents this layer type.
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
QgsRandomMarkerFillSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
void setMapUnitScale(const QgsMapUnitScale &scale) override
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
void stopFeatureRender(const QgsFeature &feature, QgsRenderContext &context) override
Called after the layer has been rendered for a particular feature.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
void setCountMethod(Qgis::PointCountMethod method)
Sets the count method used to randomly fill the polygon.
bool clipPoints() const
Returns true if point markers should be clipped to the polygon boundary.
bool canCauseArtifactsBetweenAdjacentTiles() const override
Returns true if the symbol layer rendering can cause visible artifacts across a single feature when t...
void setClipPoints(bool clipped)
Sets whether point markers should be clipped to the polygon boundary.
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
QColor color() const override
Returns the "representative" color of the symbol layer.
void setSeed(unsigned long seed)
Sets the random number seed to use when generating points, or 0 if a truly random sequence will be us...
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
void setPointCount(int count)
Sets the count of random points to render in the fill.
Qgis::PointCountMethod countMethod() const
Returns the count method used to randomly fill the polygon.
double densityArea() const
Returns the density area used to count the number of points to randomly fill the polygon.
void setColor(const QColor &color) override
Sets the "representative" color for the symbol layer.
bool setSubSymbol(QgsSymbol *symbol) FINAL
Sets layer's subsymbol. takes ownership of the passed symbol.
void setDensityArea(double area)
Sets the density area used to count the number of points to randomly fill the polygon.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
QgsMapUnitScale mapUnitScale() const override
A class for filling symbols with a repeated raster image.
void applyDataDefinedSettings(QgsSymbolRenderContext &context) override
Applies data defined settings prior to generating the fill symbol brush.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
double width() const
Returns the width used for scaling the image used in the fill.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
void renderPolygon(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context) override
Renders the fill symbol layer for the polygon whose outer ring is defined by points,...
static QgsSymbolLayer * createFromSld(QDomElement &element)
Creates a new QgsRasterFillSymbolLayer from a SLD element.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsRasterFillSymbolLayer from a properties map.
QString layerType() const override
Returns a string that represents this layer type.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
QgsRasterFillSymbolLayer(const QString &imageFilePath=QString())
Constructor for QgsRasterFillSymbolLayer, using a raster fill from the specified imageFilePath.
double opacity() const
Returns the opacity for the raster image used in the fill.
~QgsRasterFillSymbolLayer() override
void setOpacity(double opacity)
Sets the opacity for the raster image used in the fill.
QColor color() const override
Returns the "representative" color of the symbol layer.
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
QString imageFilePath() const
The path to the raster image used for the fill.
void setImageFilePath(const QString &imagePath)
Sets the path to the raster image used for the fill.
double height() const
Returns the height used for scaling the image used in the fill.
static void resolvePaths(QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving)
Turns relative paths in properties map to absolute when reading and vice versa when writing.
QPointF offset() const
Returns the offset for the fill.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
QgsRasterFillSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
bool applyBrushTransformFromContext(QgsSymbolRenderContext *context=nullptr) const override
Returns true if the image brush should be transformed using the render context's texture origin.
void setCoordinateMode(Qgis::SymbolCoordinateReference mode)
Set the coordinate mode for fill.
A rectangle specified with double values.
QgsPointXY center() const
Returns the center point of the rectangle.
Contains information about the context of a rendering operation.
void setForceVectorOutput(bool force)
Sets whether rendering operations should use vector operations instead of any faster raster shortcuts...
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
void setScaleFactor(double factor)
Sets the scaling factor for the render to convert painter units to physical sizes.
QSet< QString > disabledSymbolLayersV2() const
When rendering a map layer in a second pass (for selective masking), some symbol layers may be disabl...
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
QPainter * painter()
Returns the destination QPainter for the render operation.
double rendererScale() const
Returns the renderer map scale.
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
QgsExpressionContext & expressionContext()
Gets the expression context.
bool forceVectorOutput() const
Returns true if rendering operations should use vector operations instead of any faster raster shortc...
void setDisabledSymbolLayersV2(const QSet< QString > &symbolLayers)
When rendering a map layer in a second pass (for selective masking), some symbol layers may be disabl...
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
QColor selectionColor() const
Returns the color to use when rendering selected features.
void setMapToPixel(const QgsMapToPixel &mtp)
Sets the context's map to pixel transform, which transforms between map coordinates and device coordi...
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly during rendering to check if rendering shou...
QPointF textureOrigin() const
Returns the texture origin, which should be used as a brush transform when rendering using QBrush obj...
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
bool renderingStopped() const
Returns true if the rendering operation has been stopped and any ongoing rendering should be canceled...
static QgsRenderContext fromQPainter(QPainter *painter)
Creates a default render context given a pixel based QPainter destination.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
void setRendererScale(double scale)
Sets the renderer map scale.
Qgis::RenderContextFlags flags() const
Returns combination of flags used for rendering.
const QgsPathResolver & pathResolver() const
Returns the path resolver for conversion between relative and absolute paths during rendering operati...
A class for filling symbols with a repeated SVG file.
void renderPolygon(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context) override
Renders the fill symbol layer for the polygon whose outer ring is defined by points,...
void setParameters(const QMap< QString, QgsProperty > ¶meters)
Sets the dynamic SVG parameters.
QString svgFilePath() const
Returns the path to the SVG file used to render the fill.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
QColor dxfColor(QgsSymbolRenderContext &context) const override
Gets color.
static QgsSymbolLayer * createFromSld(QDomElement &element)
Creates a new QgsSVGFillSymbolLayer from a SLD element.
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
QColor svgStrokeColor() const
Returns the stroke color used for rendering the SVG content.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
Qgis::RenderUnit patternWidthUnit() const
Returns the units for the width of the SVG images in the pattern.
const QgsMapUnitScale & svgStrokeWidthMapUnitScale() const
Returns the map unit scale for the pattern's stroke.
double svgStrokeWidth() const
Returns the stroke width used for rendering the SVG content.
QString layerType() const override
Returns a string that represents this layer type.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
QMap< QString, QgsProperty > parameters() const
Returns the dynamic SVG parameters.
QgsSVGFillSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
QgsSVGFillSymbolLayer(const QString &svgFilePath, double width=20, double rotation=0.0)
Constructor for QgsSVGFillSymbolLayer, using the SVG picture at the specified absolute file path.
void setSvgFilePath(const QString &svgPath)
Sets the path to the SVG file to render in the fill.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsSVGFillSymbolLayer from a properties map.
QColor svgFillColor() const
Returns the fill color used for rendering the SVG content.
static void resolvePaths(QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving)
Turns relative paths in properties map to absolute when reading and vice versa when writing.
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
const QgsMapUnitScale & patternWidthMapUnitScale() const
Returns the map unit scale for the pattern's width.
Qgis::RenderUnit svgStrokeWidthUnit() const
Returns the units for the stroke width.
double patternWidth() const
Returns the width of the rendered SVG content within the fill (i.e.
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
~QgsSVGFillSymbolLayer() override
void setMapUnitScale(const QgsMapUnitScale &scale) override
void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props) const override
Saves the symbol layer as SLD.
void applyDataDefinedSettings(QgsSymbolRenderContext &context) override
Applies data defined settings prior to generating the fill symbol brush.
QgsMapUnitScale mapUnitScale() const override
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
Scoped object for saving and restoring a QPainter object's state.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
QgsShapeburstFillSymbolLayer(const QColor &color=DEFAULT_SIMPLEFILL_COLOR, const QColor &color2=Qt::white, Qgis::GradientColorSource colorType=Qgis::GradientColorSource::SimpleTwoColor, int blurRadius=0, bool useWholeShape=true, double maxDistance=5)
Constructor for QgsShapeburstFillSymbolLayer.
QgsShapeburstFillSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
~QgsShapeburstFillSymbolLayer() override
int blurRadius() const
Returns the blur radius, which controls the amount of blurring applied to the fill.
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
QColor color2() const
Returns the color used for the endpoint of the shapeburst fill.
void setMapUnitScale(const QgsMapUnitScale &scale) override
QgsMapUnitScale mapUnitScale() const override
void renderPolygon(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context) override
Renders the fill symbol layer for the polygon whose outer ring is defined by points,...
bool canCauseArtifactsBetweenAdjacentTiles() const override
Returns true if the symbol layer rendering can cause visible artifacts across a single feature when t...
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsShapeburstFillSymbolLayer using the specified properties map containing symbol prope...
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
QPointF offset() const
Returns the offset for the shapeburst fill.
bool useWholeShape() const
Returns whether the shapeburst fill is set to cover the entire shape.
bool ignoreRings() const
Returns whether the shapeburst fill is set to ignore polygon interior rings.
double maxDistance() const
Returns the maximum distance from the shape's boundary which is shaded.
QString layerType() const override
Returns a string that represents this layer type.
Qgis::GradientColorSource colorType() const
Returns the color mode used for the shapeburst fill.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
void setColorRamp(QgsColorRamp *ramp)
Sets the color ramp used to draw the shapeburst fill.
QgsSimpleFillSymbolLayer(const QColor &color=DEFAULT_SIMPLEFILL_COLOR, Qt::BrushStyle style=DEFAULT_SIMPLEFILL_STYLE, const QColor &strokeColor=DEFAULT_SIMPLEFILL_BORDERCOLOR, Qt::PenStyle strokeStyle=DEFAULT_SIMPLEFILL_BORDERSTYLE, double strokeWidth=DEFAULT_SIMPLEFILL_BORDERWIDTH, Qt::PenJoinStyle penJoinStyle=DEFAULT_SIMPLEFILL_JOINSTYLE)
double dxfWidth(const QgsDxfExport &e, QgsSymbolRenderContext &context) const override
Gets line width.
Qt::PenJoinStyle penJoinStyle() const
QColor strokeColor() const override
Returns the stroke color for the symbol layer.
QColor dxfBrushColor(QgsSymbolRenderContext &context) const override
Gets brush/fill color.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
Qt::BrushStyle dxfBrushStyle() const override
Gets brush/fill style.
QString ogrFeatureStyle(double mmScaleFactor, double mapUnitScaleFactor) const override
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
Qgis::RenderUnit mOffsetUnit
~QgsSimpleFillSymbolLayer() override
void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props) const override
Saves the symbol layer as SLD.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QColor dxfColor(QgsSymbolRenderContext &context) const override
Gets color.
QColor fillColor() const override
Returns the fill color for the symbol layer.
Qt::PenStyle strokeStyle() const
QString layerType() const override
Returns a string that represents this layer type.
double dxfAngle(QgsSymbolRenderContext &context) const override
Gets angle.
void setOutputUnit(Qgis::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
QgsMapUnitScale mOffsetMapUnitScale
double strokeWidth() const
Qgis::RenderUnit mStrokeWidthUnit
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
QPointF offset() const
Returns the offset by which polygons will be translated during rendering.
Qt::PenStyle dxfPenStyle() const override
Gets pen style.
QgsMapUnitScale mStrokeWidthMapUnitScale
QImage toTiledPatternImage() const override
Renders the symbol layer as an image that can be used as a seamless pattern fill for polygons,...
void renderPolygon(const QPolygonF &points, const QVector< QPolygonF > *rings, QgsSymbolRenderContext &context) override
Renders the fill symbol layer for the polygon whose outer ring is defined by points,...
QgsSimpleFillSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
Qt::PenStyle mStrokeStyle
QgsMapUnitScale mapUnitScale() const override
Qgis::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
Qt::PenJoinStyle mPenJoinStyle
Qt::BrushStyle mBrushStyle
void setMapUnitScale(const QgsMapUnitScale &scale) override
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsSimpleFillSymbolLayer using the specified properties map containing symbol propertie...
static QgsSymbolLayer * createFromSld(QDomElement &element)
The QgsSldExportContext class holds SLD export options and other information related to SLD export of...
QByteArray getImageData(const QString &path, bool blocking=false) const
Gets the SVG content corresponding to the given path.
QPicture svgAsPicture(const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, bool forceVectorOutput=false, double fixedAspectRatio=0, bool blocking=false, const QMap< QString, QString > ¶meters=QMap< QString, QString >())
Returns an SVG drawing as a QPicture.
void containsParams(const QString &path, bool &hasFillParam, QColor &defaultFillColor, bool &hasStrokeParam, QColor &defaultStrokeColor, bool &hasStrokeWidthParam, double &defaultStrokeWidth, bool blocking=false) const
Tests if an SVG file contains parameters for fill, stroke color, stroke width.
QImage svgAsImage(const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, bool &fitsInCache, double fixedAspectRatio=0, bool blocking=false, const QMap< QString, QString > ¶meters=QMap< QString, QString >())
Returns an SVG drawing as a QImage.
static bool rotationFromSldElement(QDomElement &element, QString &rotationFunc)
static Qgis::MarkerClipMode decodeMarkerClipMode(const QString &string, bool *ok=nullptr)
Decodes a string representing a marker clip mode.
static QString encodePenStyle(Qt::PenStyle style)
static Qt::PenJoinStyle decodePenJoinStyle(const QString &str)
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
static QgsStringMap evaluatePropertiesMap(const QMap< QString, QgsProperty > &propertiesMap, const QgsExpressionContext &context)
Evaluates a map of properties using the given context and returns a variant map with evaluated expres...
static bool displacementFromSldElement(QDomElement &element, QPointF &offset)
static QPointF polygonCentroid(const QPolygonF &points)
Calculate the centroid point of a QPolygonF.
static QString encodeBrushStyle(Qt::BrushStyle style)
static QString svgSymbolPathToName(const QString &path, const QgsPathResolver &pathResolver)
Determines an SVG symbol's name from its path.
static void externalGraphicToSld(QDomDocument &doc, QDomElement &element, const QString &path, const QString &mime, const QColor &color, double size=-1)
static QPointF polygonPointOnSurface(const QPolygonF &points, const QVector< QPolygonF > *rings=nullptr)
Calculate a point on the surface of a QPolygonF.
static QPointF toPoint(const QVariant &value, bool *ok=nullptr)
Converts a value to a point.
static void multiplyImageOpacity(QImage *image, qreal opacity)
Multiplies opacity of image pixel values with a (global) transparency value.
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
static double rescaleUom(double size, Qgis::RenderUnit unit, const QVariantMap &props)
Rescales the given size based on the uomScale found in the props, if any is found,...
static QString ogrFeatureStylePen(double width, double mmScaleFactor, double mapUnitsScaleFactor, const QColor &c, Qt::PenJoinStyle joinStyle=Qt::MiterJoin, Qt::PenCapStyle capStyle=Qt::FlatCap, double offset=0.0, const QVector< qreal > *dashPattern=nullptr)
Create ogr feature style string for pen.
static bool externalGraphicFromSld(QDomElement &element, QString &path, QString &mime, QColor &color, double &size)
static void parametricSvgToSld(QDomDocument &doc, QDomElement &graphicElem, const QString &path, const QColor &fillColor, double size, const QColor &strokeColor, double strokeWidth)
Encodes a reference to a parametric SVG into SLD, as a succession of parametric SVG using URL paramet...
static bool lineFromSld(QDomElement &element, Qt::PenStyle &penStyle, QColor &color, double &width, Qt::PenJoinStyle *penJoinStyle=nullptr, Qt::PenCapStyle *penCapStyle=nullptr, QVector< qreal > *customDashPattern=nullptr, double *dashOffset=nullptr)
static QString ogrFeatureStyleBrush(const QColor &fillColr)
Create ogr feature style string for brush.
static QString encodeLineClipMode(Qgis::LineClipMode mode)
Encodes a line clip mode to a string.
static Qgis::LineClipMode decodeLineClipMode(const QString &string, bool *ok=nullptr)
Decodes a string representing a line clip mode.
static QPointF pointOnLineWithDistance(QPointF startPoint, QPointF directionPoint, double distance)
Returns a point on the line from startPoint to directionPoint that is a certain distance away from th...
static QSize tileSize(int width, int height, double &angleRad)
Calculate the minimum size in pixels of a symbol tile given the symbol width and height and the symbo...
static Qt::BrushStyle decodeBrushStyle(const QString &str)
static void lineToSld(QDomDocument &doc, QDomElement &element, Qt::PenStyle penStyle, const QColor &color, double width=-1, const Qt::PenJoinStyle *penJoinStyle=nullptr, const Qt::PenCapStyle *penCapStyle=nullptr, const QVector< qreal > *customDashPattern=nullptr, double dashOffset=0.0)
static QDomElement createVendorOptionElement(QDomDocument &doc, const QString &name, const QString &value)
static bool wellKnownMarkerFromSld(QDomElement &element, QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle, double &strokeWidth, double &size)
static void createDisplacementElement(QDomDocument &doc, QDomElement &element, QPointF offset)
static QString svgSymbolNameToPath(const QString &name, const QgsPathResolver &pathResolver)
Determines an SVG symbol's path from its name.
static QString encodeColor(const QColor &color)
static bool fillFromSld(QDomElement &element, Qt::BrushStyle &brushStyle, QColor &color)
static void fillToSld(QDomDocument &doc, QDomElement &element, Qt::BrushStyle brushStyle, const QColor &color=QColor())
static Qgis::RenderUnit decodeSldUom(const QString &str, double *scaleFactor=nullptr)
Decodes a SLD unit of measure string to a render unit.
static void createGeometryElement(QDomDocument &doc, QDomElement &element, const QString &geomFunc)
static double estimateMaxSymbolBleed(QgsSymbol *symbol, const QgsRenderContext &context)
Returns the maximum estimated bleed for the symbol.
static void wellKnownMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &name, const QColor &color, const QColor &strokeColor, Qt::PenStyle strokeStyle, double strokeWidth=-1, double size=-1)
static Qt::PenStyle decodePenStyle(const QString &str)
static void createRotationElement(QDomDocument &doc, QDomElement &element, const QString &rotationFunc)
static Qgis::SymbolCoordinateReference decodeCoordinateReference(const QString &string, bool *ok=nullptr)
Decodes a string representing a symbol coordinate reference mode.
static QString encodePoint(QPointF point)
Encodes a QPointF to a string.
static QgsSymbolLayer * createMarkerLayerFromSld(QDomElement &element)
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
static QgsStringMap getVendorOptionList(QDomElement &element)
static QPointF decodePoint(const QString &string)
Decodes a QSizeF from a string.
static QgsSymbolLayer * createLineLayerFromSld(QDomElement &element)
static QString encodeCoordinateReference(Qgis::SymbolCoordinateReference coordinateReference)
Encodes a symbol coordinate reference mode to a string.
static QString encodeMarkerClipMode(Qgis::MarkerClipMode mode)
Encodes a marker clip mode to a string.
virtual bool setSubSymbol(QgsSymbol *symbol)
Sets layer's subsymbol. takes ownership of the passed symbol.
bool shouldRenderUsingSelectionColor(const QgsSymbolRenderContext &context) const
Returns true if the symbol layer should be rendered using the selection color from the render context...
Qgis::SymbolType type() const
virtual QColor fillColor() const
Returns the fill color for the symbol layer.
static const bool SELECTION_IS_OPAQUE
Whether styles for selected features ignore symbol alpha.
void removeMasks(QgsRenderContext &context, bool recursive)
When rendering, remove previously installed masks from context painter if recursive is true masks are...
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns the set of attributes referenced by the layer.
void copyDataDefinedProperties(QgsSymbolLayer *destLayer) const
Copies all data defined properties of this layer to another symbol layer.
@ GradientType
Gradient fill type.
@ SecondaryColor
Secondary color (eg for gradient fills)
@ File
Filename, eg for svg files.
@ GradientReference2Y
Gradient reference point 2 y.
@ GradientReference1X
Gradient reference point 1 x.
@ OffsetY
Vertical offset.
@ OffsetX
Horizontal offset.
@ GradientReference1Y
Gradient reference point 1 y.
@ GradientSpread
Gradient spread mode.
@ ShapeburstMaxDistance
Shapeburst fill from edge distance.
@ StrokeStyle
Stroke style (eg solid, dashed)
@ DistanceY
Vertical distance between points.
@ DensityArea
Density area.
@ ClipPoints
Whether markers should be clipped to polygon boundaries.
@ LineClipping
Line clipping mode (since QGIS 3.24)
@ ShapeburstIgnoreRings
Shapeburst ignore rings.
@ ShapeburstUseWholeShape
Shapeburst use whole shape.
@ DisplacementX
Horizontal displacement.
@ CoordinateMode
Gradient coordinate mode.
@ FillStyle
Fill style (eg solid, dots)
@ GradientReference2X
Gradient reference point 2 x.
@ StrokeColor
Stroke color.
@ BlurRadius
Shapeburst blur radius.
@ MarkerClipping
Marker clipping mode (since QGIS 3.24)
@ RandomSeed
Random number seed.
@ LineAngle
Line angle, or angle of hash lines for hash line symbols.
@ JoinStyle
Line join style.
@ RandomOffsetY
Random offset Y (since QGIS 3.24)
@ DisplacementY
Vertical displacement.
@ DistanceX
Horizontal distance between points.
@ GradientReference1IsCentroid
Gradient reference point 1 is centroid.
@ StrokeWidth
Stroke width.
@ GradientReference2IsCentroid
Gradient reference point 2 is centroid.
@ LineDistance
Distance between lines, or length of lines for hash line symbols.
@ RandomOffsetX
Random offset X (since QGIS 3.24)
void installMasks(QgsRenderContext &context, bool recursive)
When rendering, install masks on context painter if recursive is true masks are installed recursively...
virtual double estimateMaxBleed(const QgsRenderContext &context) const
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
static const bool SELECT_FILL_BORDER
Whether fill styles for selected features also highlight symbol stroke.
virtual QString layerType() const =0
Returns a string that represents this layer type.
virtual QColor color() const
Returns the "representative" color of the symbol layer.
virtual QColor strokeColor() const
Returns the stroke color for the symbol layer.
void copyPaintEffect(QgsSymbolLayer *destLayer) const
Copies paint effect of this layer to another symbol layer.
QgsPropertyCollection mDataDefinedProperties
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
static const bool SELECT_FILL_STYLE
Whether fill styles for selected features uses symbol layer style.
virtual bool hasDataDefinedProperties() const
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
const QgsFeature * feature() const
Returns the current feature being rendered.
QgsFields fields() const
Fields of the layer.
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for data defined symbology.
qreal opacity() const
Returns the opacity for the symbol.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
Abstract base class for all rendered symbols.
QColor color() const
Returns the symbol's color.
Qgis::SymbolType type() const
Returns the symbol's type.
double interval() const
Returns the interval between individual symbols.
const QgsMapUnitScale & intervalMapUnitScale() const
Returns the map unit scale for the interval between symbols.
void setInterval(double interval)
Sets the interval between individual symbols.
Qgis::RenderUnit intervalUnit() const
Returns the units for the interval between symbols.
static Q_INVOKABLE Qgis::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QMap< QString, QString > QgsStringMap
#define DEFAULT_SIMPLEFILL_JOINSTYLE
#define DEFAULT_SIMPLEFILL_COLOR
#define DEFAULT_SIMPLEFILL_STYLE
#define DEFAULT_SIMPLEFILL_BORDERSTYLE
#define DEFAULT_SIMPLEFILL_BORDERCOLOR
#define DEFAULT_SIMPLEFILL_BORDERWIDTH
QList< QgsSymbolLayer * > QgsSymbolLayerList
Single variable definition for use within a QgsExpressionContextScope.