40 #include <QSvgRenderer> 
   41 #include <QDomDocument> 
   42 #include <QDomElement> 
   50     Qt::PenJoinStyle penJoinStyle )
 
   51   : mBrushStyle( style )
 
   52   , mStrokeColor( strokeColor )
 
   53   , mStrokeStyle( strokeStyle )
 
   54   , mStrokeWidth( strokeWidth )
 
   55   , mPenJoinStyle( penJoinStyle )
 
   91 void QgsSimpleFillSymbolLayer::applyDataDefinedSymbology( 
QgsSymbolRenderContext &context, QBrush &brush, QPen &pen, QPen &selPen )
 
  107     if ( exprVal.isValid() )
 
  119     double width = exprVal.toDouble( &ok );
 
  123       pen.setWidthF( width );
 
  124       selPen.setWidthF( width );
 
  160   if ( props.contains( QStringLiteral( 
"color" ) ) )
 
  162   if ( props.contains( QStringLiteral( 
"style" ) ) )
 
  164   if ( props.contains( QStringLiteral( 
"color_border" ) ) )
 
  169   else if ( props.contains( QStringLiteral( 
"outline_color" ) ) )
 
  173   else if ( props.contains( QStringLiteral( 
"line_color" ) ) )
 
  178   if ( props.contains( QStringLiteral( 
"style_border" ) ) )
 
  183   else if ( props.contains( QStringLiteral( 
"outline_style" ) ) )
 
  187   else if ( props.contains( QStringLiteral( 
"line_style" ) ) )
 
  191   if ( props.contains( QStringLiteral( 
"width_border" ) ) )
 
  194     strokeWidth = props[QStringLiteral( 
"width_border" )].toDouble();
 
  196   else if ( props.contains( QStringLiteral( 
"outline_width" ) ) )
 
  198     strokeWidth = props[QStringLiteral( 
"outline_width" )].toDouble();
 
  200   else if ( props.contains( QStringLiteral( 
"line_width" ) ) )
 
  202     strokeWidth = props[QStringLiteral( 
"line_width" )].toDouble();
 
  204   if ( props.contains( QStringLiteral( 
"offset" ) ) )
 
  206   if ( props.contains( QStringLiteral( 
"joinstyle" ) ) )
 
  211   if ( props.contains( QStringLiteral( 
"border_width_unit" ) ) )
 
  215   else if ( props.contains( QStringLiteral( 
"outline_width_unit" ) ) )
 
  219   else if ( props.contains( QStringLiteral( 
"line_width_unit" ) ) )
 
  223   if ( props.contains( QStringLiteral( 
"offset_unit" ) ) )
 
  226   if ( props.contains( QStringLiteral( 
"border_width_map_unit_scale" ) ) )
 
  228   if ( props.contains( QStringLiteral( 
"offset_map_unit_scale" ) ) )
 
  231   sl->restoreOldDataDefinedProperties( props );
 
  239   return QStringLiteral( 
"SimpleFill" );
 
  251     selColor.setAlphaF( context.
opacity() );
 
  290 #ifndef QT_NO_PRINTER 
  291   if ( 
mBrush.style() == Qt::SolidPattern || 
mBrush.style() == Qt::NoBrush || !
dynamic_cast<QPrinter *
>( p->device() ) )
 
  298 #ifndef QT_NO_PRINTER 
  305     p->setPen( Qt::NoPen );
 
  309     p->setBrush( Qt::NoBrush );
 
  327   map[QStringLiteral( 
"outline_width" )] = QString::number( 
mStrokeWidth );
 
  355   QDomElement symbolizerElem = doc.createElement( QStringLiteral( 
"se:PolygonSymbolizer" ) );
 
  356   if ( !props.value( QStringLiteral( 
"uom" ), QString() ).isEmpty() )
 
  357     symbolizerElem.setAttribute( QStringLiteral( 
"uom" ), props.value( QStringLiteral( 
"uom" ), QString() ) );
 
  358   element.appendChild( symbolizerElem );
 
  366     QDomElement fillElem = doc.createElement( QStringLiteral( 
"se:Fill" ) );
 
  367     symbolizerElem.appendChild( fillElem );
 
  374     QDomElement strokeElem = doc.createElement( QStringLiteral( 
"se:Stroke" ) );
 
  375     symbolizerElem.appendChild( strokeElem );
 
  390   symbolStyle.append( 
';' );
 
  399   Qt::BrushStyle fillStyle;
 
  403   QDomElement fillElem = element.firstChildElement( QStringLiteral( 
"Fill" ) );
 
  406   QDomElement strokeElem = element.firstChildElement( QStringLiteral( 
"Stroke" ) );
 
  412   QString uom = element.attribute( QStringLiteral( 
"uom" ), QString() );
 
  418   sl->setOutputUnit( QgsUnitTypes::RenderUnit::RenderPixels );
 
  427   return penBleed + offsetBleed;
 
  488   : mGradientColorType( colorType )
 
  489   , mGradientType( gradientType )
 
  490   , mCoordinateMode( coordinateMode )
 
  491   , mGradientSpread( spread )
 
  492   , mReferencePoint1( QPointF( 0.5, 0 ) )
 
  493   , mReferencePoint2( QPointF( 0.5, 1 ) )
 
  514   bool refPoint1IsCentroid = 
false;
 
  516   bool refPoint2IsCentroid = 
false;
 
  521   if ( props.contains( QStringLiteral( 
"type" ) ) )
 
  522     type = 
static_cast< GradientType >( props[QStringLiteral( 
"type" )].toInt() );
 
  523   if ( props.contains( QStringLiteral( 
"coordinate_mode" ) ) )
 
  525   if ( props.contains( QStringLiteral( 
"spread" ) ) )
 
  527   if ( props.contains( QStringLiteral( 
"color_type" ) ) )
 
  528     colorType = 
static_cast< GradientColorType >( props[QStringLiteral( 
"color_type" )].toInt() );
 
  529   if ( props.contains( QStringLiteral( 
"gradient_color" ) ) )
 
  534   else if ( props.contains( QStringLiteral( 
"color" ) ) )
 
  538   if ( props.contains( QStringLiteral( 
"gradient_color2" ) ) )
 
  543   if ( props.contains( QStringLiteral( 
"reference_point1" ) ) )
 
  545   if ( props.contains( QStringLiteral( 
"reference_point1_iscentroid" ) ) )
 
  546     refPoint1IsCentroid = props[QStringLiteral( 
"reference_point1_iscentroid" )].toInt();
 
  547   if ( props.contains( QStringLiteral( 
"reference_point2" ) ) )
 
  549   if ( props.contains( QStringLiteral( 
"reference_point2_iscentroid" ) ) )
 
  550     refPoint2IsCentroid = props[QStringLiteral( 
"reference_point2_iscentroid" )].toInt();
 
  551   if ( props.contains( QStringLiteral( 
"angle" ) ) )
 
  552     angle = props[QStringLiteral( 
"angle" )].toDouble();
 
  554   if ( props.contains( QStringLiteral( 
"offset" ) ) )
 
  559   if ( props.contains( QStringLiteral( 
"rampType" ) ) && props[QStringLiteral( 
"rampType" )] == QStringLiteral( 
"cpt-city" ) )
 
  571   if ( props.contains( QStringLiteral( 
"offset_unit" ) ) )
 
  573   if ( props.contains( QStringLiteral( 
"offset_map_unit_scale" ) ) )
 
  576   sl->setReferencePoint1IsCentroid( refPoint1IsCentroid );
 
  578   sl->setReferencePoint2IsCentroid( refPoint2IsCentroid );
 
  579   sl->setAngle( 
angle );
 
  581     sl->setColorRamp( gradientRamp );
 
  583   sl->restoreOldDataDefinedProperties( props );
 
  596   return QStringLiteral( 
"GradientFill" );
 
  599 void QgsGradientFillSymbolLayer::applyDataDefinedSymbology( 
QgsSymbolRenderContext &context, 
const QPolygonF &points )
 
  642       if ( currentType == QObject::tr( 
"linear" ) )
 
  646       else if ( currentType == QObject::tr( 
"radial" ) )
 
  650       else if ( currentType == QObject::tr( 
"conical" ) )
 
  664       if ( currentCoordMode == QObject::tr( 
"feature" ) )
 
  668       else if ( currentCoordMode == QObject::tr( 
"viewport" ) )
 
  682       if ( currentSpread == QObject::tr( 
"pad" ) )
 
  686       else if ( currentSpread == QObject::tr( 
"repeat" ) )
 
  690       else if ( currentSpread == QObject::tr( 
"reflect" ) )
 
  737   if ( refPoint1IsCentroid || refPoint2IsCentroid )
 
  742     QRectF bbox = points.boundingRect();
 
  743     double centroidX = ( centroid.x() - bbox.left() ) / bbox.width();
 
  744     double centroidY = ( centroid.y() - bbox.top() ) / bbox.height();
 
  746     if ( refPoint1IsCentroid )
 
  748       refPoint1X = centroidX;
 
  749       refPoint1Y = centroidY;
 
  751     if ( refPoint2IsCentroid )
 
  753       refPoint2X = centroidX;
 
  754       refPoint2Y = centroidY;
 
  760                  spread, QPointF( refPoint1X, refPoint1Y ), QPointF( refPoint2X, refPoint2Y ), 
angle );
 
  763 QPointF QgsGradientFillSymbolLayer::rotateReferencePoint( QPointF refPoint, 
double angle )
 
  768   QLineF refLine = QLineF( QPointF( 0.5, 0.5 ), refPoint );
 
  770   refLine.setAngle( refLine.angle() + 
angle );
 
  772   QPointF rotatedReferencePoint = refLine.p2();
 
  774   if ( rotatedReferencePoint.x() > 1 )
 
  775     rotatedReferencePoint.setX( 1 );
 
  776   if ( rotatedReferencePoint.x() < 0 )
 
  777     rotatedReferencePoint.setX( 0 );
 
  778   if ( rotatedReferencePoint.y() > 1 )
 
  779     rotatedReferencePoint.setY( 1 );
 
  780   if ( rotatedReferencePoint.y() < 0 )
 
  781     rotatedReferencePoint.setY( 0 );
 
  783   return rotatedReferencePoint;
 
  787     const QColor &color, 
const QColor &color2, GradientColorType gradientColorType,
 
  789     GradientCoordinateMode coordinateMode, GradientSpread gradientSpread,
 
  790     QPointF referencePoint1, QPointF referencePoint2, 
const double angle )
 
  795   QColor fillColor2 = 
color2;
 
  796   fillColor2.setAlphaF( context.
opacity() * fillColor2.alphaF() );
 
  807       gradient = QLinearGradient( rotatedReferencePoint1, rotatedReferencePoint2 );
 
  810       gradient = QRadialGradient( rotatedReferencePoint1, QLineF( rotatedReferencePoint1, rotatedReferencePoint2 ).length() );
 
  813       gradient = QConicalGradient( rotatedReferencePoint1, QLineF( rotatedReferencePoint1, rotatedReferencePoint2 ).
angle() );
 
  819       gradient.setCoordinateMode( QGradient::ObjectBoundingMode );
 
  822       gradient.setCoordinateMode( QGradient::StretchToDeviceMode );
 
  828       gradient.setSpread( QGradient::PadSpread );
 
  831       gradient.setSpread( QGradient::ReflectSpread );
 
  834       gradient.setSpread( QGradient::RepeatSpread );
 
  840        ( gradientRamp->
type() == QLatin1String( 
"gradient" ) || gradientRamp->
type() == QLatin1String( 
"cpt-city" ) ) )
 
  850     gradient.setColorAt( 1.0, fillColor2 );
 
  854   brush = QBrush( gradient );
 
  861     selColor.setAlphaF( context.
opacity() );
 
  878   applyDataDefinedSymbology( context, points );
 
  881   p->setPen( Qt::NoPen );
 
  905   map[QStringLiteral( 
"type" )] = QString::number( 
mGradientType );
 
  906   map[QStringLiteral( 
"coordinate_mode" )] = QString::number( 
mCoordinateMode );
 
  912   map[QStringLiteral( 
"angle" )] = QString::number( 
mAngle );
 
  970     int blurRadius, 
bool useWholeShape, 
double maxDistance )
 
  971   : mBlurRadius( blurRadius )
 
  972   , mUseWholeShape( useWholeShape )
 
  973   , mMaxDistance( maxDistance )
 
  974   , mColorType( colorType )
 
  993   if ( props.contains( QStringLiteral( 
"color_type" ) ) )
 
  997   if ( props.contains( QStringLiteral( 
"shapeburst_color" ) ) )
 
 1002   else if ( props.contains( QStringLiteral( 
"color" ) ) )
 
 1007   if ( props.contains( QStringLiteral( 
"shapeburst_color2" ) ) )
 
 1012   else if ( props.contains( QStringLiteral( 
"gradient_color2" ) ) )
 
 1016   if ( props.contains( QStringLiteral( 
"blur_radius" ) ) )
 
 1018     blurRadius = props[QStringLiteral( 
"blur_radius" )].toInt();
 
 1020   if ( props.contains( QStringLiteral( 
"use_whole_shape" ) ) )
 
 1022     useWholeShape = props[QStringLiteral( 
"use_whole_shape" )].toInt();
 
 1024   if ( props.contains( QStringLiteral( 
"max_distance" ) ) )
 
 1026     maxDistance = props[QStringLiteral( 
"max_distance" )].toDouble();
 
 1028   if ( props.contains( QStringLiteral( 
"offset" ) ) )
 
 1035   if ( props.contains( QStringLiteral( 
"rampType" ) ) && props[QStringLiteral( 
"rampType" )] == QStringLiteral( 
"cpt-city" ) )
 
 1047   if ( props.contains( QStringLiteral( 
"offset_unit" ) ) )
 
 1051   if ( props.contains( QStringLiteral( 
"distance_unit" ) ) )
 
 1055   if ( props.contains( QStringLiteral( 
"offset_map_unit_scale" ) ) )
 
 1059   if ( props.contains( QStringLiteral( 
"distance_map_unit_scale" ) ) )
 
 1063   if ( props.contains( QStringLiteral( 
"ignore_rings" ) ) )
 
 1065     sl->setIgnoreRings( props[QStringLiteral( 
"ignore_rings" )].toInt() );
 
 1069     sl->setColorRamp( gradientRamp );
 
 1072   sl->restoreOldDataDefinedProperties( props );
 
 1074   return sl.release();
 
 1079   return QStringLiteral( 
"ShapeburstFill" );
 
 1084   if ( mGradientRamp.get() == ramp )
 
 1087   mGradientRamp.reset( ramp );
 
 1090 void QgsShapeburstFillSymbolLayer::applyDataDefinedSymbology( 
QgsSymbolRenderContext &context, QColor &color, QColor &color2, 
int &blurRadius, 
bool &useWholeShape,
 
 1091     double &maxDistance, 
bool &ignoreRings )
 
 1148     selColor.setAlphaF( context.
opacity() );
 
 1149   mSelBrush = QBrush( selColor );
 
 1168     p->setBrush( mSelBrush );
 
 1170     if ( !mOffset.isNull() )
 
 1177     if ( !mOffset.isNull() )
 
 1193   int outputPixelMaxDist = 0;
 
 1201   std::unique_ptr< QgsGradientColorRamp > twoColorGradientRamp;
 
 1204     twoColorGradientRamp = qgis::make_unique< QgsGradientColorRamp >( color1, 
color2 );
 
 1208   p->setPen( QPen( Qt::NoPen ) );
 
 1213   int pointsWidth = 
static_cast< int >( std::round( points.boundingRect().width() ) );
 
 1214   int pointsHeight = 
static_cast< int >( std::round( points.boundingRect().height() ) );
 
 1215   int imWidth = pointsWidth + ( sideBuffer * 2 );
 
 1216   int imHeight = pointsHeight + ( sideBuffer * 2 );
 
 1217   std::unique_ptr< QImage > fillImage = qgis::make_unique< QImage >( imWidth,
 
 1218                                         imHeight, QImage::Format_ARGB32_Premultiplied );
 
 1219   if ( fillImage->isNull() )
 
 1226   std::unique_ptr< QImage > alphaImage = qgis::make_unique< QImage >( fillImage->width(), fillImage->height(), QImage::Format_ARGB32_Premultiplied );
 
 1227   if ( alphaImage->isNull() )
 
 1236   fillImage->fill( Qt::black );
 
 1239   alphaImage->fill( Qt::transparent );
 
 1242   QPainter imgPainter;
 
 1243   imgPainter.begin( alphaImage.get() );
 
 1244   imgPainter.setRenderHint( QPainter::Antialiasing, 
true );
 
 1245   imgPainter.setBrush( QBrush( Qt::white ) );
 
 1246   imgPainter.setPen( QPen( Qt::black ) );
 
 1247   imgPainter.translate( -points.boundingRect().left() + sideBuffer, - points.boundingRect().top() + sideBuffer );
 
 1253   imgPainter.begin( fillImage.get() );
 
 1256     imgPainter.drawImage( 0, 0, *alphaImage );
 
 1263     imgPainter.setBrush( QBrush( Qt::white ) );
 
 1264     imgPainter.setPen( QPen( Qt::black ) );
 
 1265     imgPainter.translate( -points.boundingRect().left() + sideBuffer, - points.boundingRect().top() + sideBuffer );
 
 1271   double *dtArray = distanceTransform( fillImage.get(), context.
renderContext() );
 
 1291   imgPainter.begin( fillImage.get() );
 
 1292   imgPainter.setCompositionMode( QPainter::CompositionMode_DestinationIn );
 
 1293   imgPainter.drawImage( 0, 0, *alphaImage );
 
 1302   if ( !mOffset.isNull() )
 
 1309   p->drawImage( points.boundingRect().left() - sideBuffer, points.boundingRect().top() - sideBuffer, *fillImage );
 
 1311   if ( !mOffset.isNull() )
 
 1322 void QgsShapeburstFillSymbolLayer::distanceTransform1d( 
double *f, 
int n, 
int *v, 
double *z, 
double *d )
 
 1328   for ( 
int q = 1; q <= n - 1; q++ )
 
 1330     double s  = ( ( f[q] + q * q ) - ( f[v[k]] + ( v[k] * v[k] ) ) ) / ( 2 * q - 2 * v[k] );
 
 1334       s  = ( ( f[q] + q * q ) - ( f[v[k]] + ( v[k] * v[k] ) ) ) / ( 2 * q - 2 * v[k] );
 
 1343   for ( 
int q = 0; q <= n - 1; q++ )
 
 1345     while ( z[k + 1] < q )
 
 1347     d[q] = ( q - v[k] ) * ( q - v[k] ) + f[v[k]];
 
 1352 void QgsShapeburstFillSymbolLayer::distanceTransform2d( 
double *im, 
int width, 
int height, 
QgsRenderContext &context )
 
 1354   int maxDimension = std::max( width, height );
 
 1355   double *f = 
new double[ maxDimension ];
 
 1356   int *v = 
new int[ maxDimension ];
 
 1357   double *z = 
new double[ maxDimension + 1 ];
 
 1358   double *d = 
new double[ maxDimension ];
 
 1361   for ( 
int x = 0; x < width; x++ )
 
 1366     for ( 
int y = 0; y < height; y++ )
 
 1368       f[y] = im[ x + y * width ];
 
 1370     distanceTransform1d( f, height, v, z, d );
 
 1371     for ( 
int y = 0; y < height; y++ )
 
 1373       im[ x + y * width ] = d[y];
 
 1378   for ( 
int y = 0; y < height; y++ )
 
 1383     for ( 
int x = 0; x < width; x++ )
 
 1385       f[x] = im[  x + y * width ];
 
 1387     distanceTransform1d( f, width, v, z, d );
 
 1388     for ( 
int x = 0; x < width; x++ )
 
 1390       im[  x + y * width ] = d[x];
 
 1401 double *QgsShapeburstFillSymbolLayer::distanceTransform( QImage *im, 
QgsRenderContext &context )
 
 1403   int width = im->width();
 
 1404   int height = im->height();
 
 1406   double *dtArray = 
new double[width * height];
 
 1411   for ( 
int heightIndex = 0; heightIndex < height; ++heightIndex )
 
 1416     const QRgb *scanLine = 
reinterpret_cast< const QRgb * 
>( im->constScanLine( heightIndex ) );
 
 1417     for ( 
int widthIndex = 0; widthIndex < width; ++widthIndex )
 
 1419       tmpRgb = scanLine[widthIndex];
 
 1420       if ( qRed( tmpRgb ) == 0 )
 
 1428         dtArray[ idx ] = 
INF;
 
 1435   distanceTransform2d( dtArray, width, height, context );
 
 1440 void QgsShapeburstFillSymbolLayer::dtArrayToQImage( 
double *array, QImage *im, 
QgsColorRamp *ramp, 
QgsRenderContext &context, 
bool useWholeShape, 
int maxPixelDistance )
 
 1442   int width = im->width();
 
 1443   int height = im->height();
 
 1446   double maxDistanceValue;
 
 1451     double dtMaxValue = array[0];
 
 1452     for ( 
int i = 1; i < ( width * height ); ++i )
 
 1454       if ( array[i] > dtMaxValue )
 
 1456         dtMaxValue = array[i];
 
 1461     maxDistanceValue = std::sqrt( dtMaxValue );
 
 1466     maxDistanceValue = maxPixelDistance;
 
 1471   double squaredVal = 0;
 
 1474   for ( 
int heightIndex = 0; heightIndex < height; ++heightIndex )
 
 1479     QRgb *scanLine = 
reinterpret_cast< QRgb * 
>( im->scanLine( heightIndex ) );
 
 1480     for ( 
int widthIndex = 0; widthIndex < width; ++widthIndex )
 
 1483       squaredVal = array[idx];
 
 1486       if ( maxDistanceValue > 0 )
 
 1488         pixVal = squaredVal > 0 ? std::min( ( std::sqrt( squaredVal ) / maxDistanceValue ), 1.0 ) : 0;
 
 1497       scanLine[widthIndex] = qPremultiply( ramp->
color( pixVal ).rgba() );
 
 1508   map[QStringLiteral( 
"color_type" )] = QString::number( mColorType );
 
 1509   map[QStringLiteral( 
"blur_radius" )] = QString::number( mBlurRadius );
 
 1510   map[QStringLiteral( 
"use_whole_shape" )] = QString::number( mUseWholeShape );
 
 1511   map[QStringLiteral( 
"max_distance" )] = QString::number( mMaxDistance );
 
 1514   map[QStringLiteral( 
"ignore_rings" )] = QString::number( mIgnoreRings );
 
 1518   if ( mGradientRamp )
 
 1520     map.unite( mGradientRamp->properties() );
 
 1528   std::unique_ptr< QgsShapeburstFillSymbolLayer > sl = qgis::make_unique< QgsShapeburstFillSymbolLayer >( 
mColor, mColor2, mColorType, mBlurRadius, mUseWholeShape, mMaxDistance );
 
 1529   if ( mGradientRamp )
 
 1531     sl->setColorRamp( mGradientRamp->clone() );
 
 1533   sl->setDistanceUnit( mDistanceUnit );
 
 1534   sl->setDistanceMapUnitScale( mDistanceMapUnitScale );
 
 1535   sl->setIgnoreRings( mIgnoreRings );
 
 1536   sl->setOffset( mOffset );
 
 1537   sl->setOffsetUnit( mOffsetUnit );
 
 1538   sl->setOffsetMapUnitScale( mOffsetMapUnitScale );
 
 1541   return sl.release();
 
 1546   double offsetBleed = context.
convertToPainterUnits( std::max( std::fabs( mOffset.x() ), std::fabs( mOffset.y() ) ), mOffsetUnit, mOffsetMapUnitScale );
 
 1552   mDistanceUnit = unit;
 
 1558   if ( mDistanceUnit == mOffsetUnit )
 
 1560     return mDistanceUnit;
 
 1567   mDistanceMapUnitScale = scale;
 
 1568   mOffsetMapUnitScale = scale;
 
 1573   if ( mDistanceMapUnitScale == mOffsetMapUnitScale )
 
 1575     return mDistanceMapUnitScale;
 
 1599   p->setPen( QPen( Qt::NoPen ) );
 
 1601   QTransform bkTransform = 
mBrush.transform();
 
 1605     QPointF leftCorner = points.boundingRect().topLeft();
 
 1606     QTransform t = 
mBrush.transform();
 
 1607     t.translate( leftCorner.x(), leftCorner.y() );
 
 1608     mBrush.setTransform( t );
 
 1614     p->setBrush( QBrush( selColor ) );
 
 1620     QTransform t = 
mBrush.transform();
 
 1622     mBrush.setTransform( t );
 
 1631       for ( 
auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
 
 1638   mBrush.setTransform( bkTransform );
 
 1690     double subLayerBleed = 
mStroke->symbolLayer( 0 )->estimateMaxBleed( context );
 
 1691     return subLayerBleed;
 
 1712     return QColor( Qt::black );
 
 1719   return Qt::SolidLine;
 
 1723     return Qt::SolidLine;
 
 1727     return mStroke->dxfPenStyle();
 
 1736     attr.unite( 
mStroke->usedAttributes( context ) );
 
 1754   , mPatternWidth( width )
 
 1758   mColor = QColor( 255, 255, 255 );
 
 1764   , mPatternWidth( width )
 
 1765   , mSvgData( svgData )
 
 1770   mColor = QColor( 255, 255, 255 );
 
 1772   setDefaultSvgParams();
 
 1778   mPatternWidthUnit = unit;
 
 1779   mSvgStrokeWidthUnit = unit;
 
 1781   mStroke->setOutputUnit( unit );
 
 1787   if ( mPatternWidthUnit != unit || mSvgStrokeWidthUnit != unit || 
mStrokeWidthUnit != unit )
 
 1797   mPatternWidthMapUnitScale = scale;
 
 1798   mSvgStrokeWidthMapUnitScale = scale;
 
 1805        mPatternWidthMapUnitScale == mSvgStrokeWidthMapUnitScale &&
 
 1808     return mPatternWidthMapUnitScale;
 
 1818   mSvgFilePath = svgPath;
 
 1819   setDefaultSvgParams();
 
 1829   if ( 
properties.contains( QStringLiteral( 
"width" ) ) )
 
 1831     width = 
properties[QStringLiteral( 
"width" )].toDouble();
 
 1833   if ( 
properties.contains( QStringLiteral( 
"svgFile" ) ) )
 
 1837   if ( 
properties.contains( QStringLiteral( 
"angle" ) ) )
 
 1842   std::unique_ptr< QgsSVGFillSymbolLayer > symbolLayer;
 
 1845     symbolLayer = qgis::make_unique< QgsSVGFillSymbolLayer >( 
svgFilePath, width, 
angle );
 
 1849     if ( 
properties.contains( QStringLiteral( 
"data" ) ) )
 
 1851       data = QByteArray::fromHex( 
properties[QStringLiteral( 
"data" )].toLocal8Bit() );
 
 1853     symbolLayer = qgis::make_unique< QgsSVGFillSymbolLayer >( data, width, 
angle );
 
 1857   if ( 
properties.contains( QStringLiteral( 
"svgFillColor" ) ) )
 
 1862   else if ( 
properties.contains( QStringLiteral( 
"color" ) ) )
 
 1866   if ( 
properties.contains( QStringLiteral( 
"svgOutlineColor" ) ) )
 
 1871   else if ( 
properties.contains( QStringLiteral( 
"outline_color" ) ) )
 
 1875   else if ( 
properties.contains( QStringLiteral( 
"line_color" ) ) )
 
 1879   if ( 
properties.contains( QStringLiteral( 
"svgOutlineWidth" ) ) )
 
 1882     symbolLayer->setSvgStrokeWidth( 
properties[QStringLiteral( 
"svgOutlineWidth" )].toDouble() );
 
 1884   else if ( 
properties.contains( QStringLiteral( 
"outline_width" ) ) )
 
 1886     symbolLayer->setSvgStrokeWidth( 
properties[QStringLiteral( 
"outline_width" )].toDouble() );
 
 1888   else if ( 
properties.contains( QStringLiteral( 
"line_width" ) ) )
 
 1890     symbolLayer->setSvgStrokeWidth( 
properties[QStringLiteral( 
"line_width" )].toDouble() );
 
 1894   if ( 
properties.contains( QStringLiteral( 
"pattern_width_unit" ) ) )
 
 1898   if ( 
properties.contains( QStringLiteral( 
"pattern_width_map_unit_scale" ) ) )
 
 1902   if ( 
properties.contains( QStringLiteral( 
"svg_outline_width_unit" ) ) )
 
 1906   if ( 
properties.contains( QStringLiteral( 
"svg_outline_width_map_unit_scale" ) ) )
 
 1910   if ( 
properties.contains( QStringLiteral( 
"outline_width_unit" ) ) )
 
 1914   if ( 
properties.contains( QStringLiteral( 
"outline_width_map_unit_scale" ) ) )
 
 1919   symbolLayer->restoreOldDataDefinedProperties( 
properties );
 
 1921   return symbolLayer.release();
 
 1926   QgsStringMap::iterator it = 
properties.find( QStringLiteral( 
"svgFile" ) );
 
 1938   return QStringLiteral( 
"SVGFill" );
 
 1941 void QgsSVGFillSymbolLayer::applyPattern( QBrush &brush, 
const QString &svgFilePath, 
double patternWidth, 
QgsUnitTypes::RenderUnit patternWidthUnit,
 
 1942     const QColor &svgFillColor, 
const QColor &svgStrokeColor, 
double svgStrokeWidth,
 
 1946   if ( mSvgViewBox.isNull() )
 
 1953   if ( 
static_cast< int >( size ) < 1.0 || 10000.0 < size )
 
 1955     brush.setTextureImage( QImage() );
 
 1959     bool fitsInCache = 
true;
 
 1967       double hwRatio = 1.0;
 
 1968       if ( patternPict.width() > 0 )
 
 1970         hwRatio = 
static_cast< double >( patternPict.height() ) / 
static_cast< double >( patternPict.width() );
 
 1972       patternImage = QImage( 
static_cast< int >( size ), 
static_cast< int >( size * hwRatio ), QImage::Format_ARGB32_Premultiplied );
 
 1973       patternImage.fill( 0 ); 
 
 1975       QPainter p( &patternImage );
 
 1976       p.drawPicture( QPointF( size / 2, size * hwRatio / 2 ), patternPict );
 
 1979     QTransform brushTransform;
 
 1982       QImage transparentImage = patternImage.copy();
 
 1984       brush.setTextureImage( transparentImage );
 
 1988       brush.setTextureImage( patternImage );
 
 1990     brush.setTransform( brushTransform );
 
 1997   applyPattern( 
mBrush, mSvgFilePath, mPatternWidth, mPatternWidthUnit, 
mColor, mSvgStrokeColor, mSvgStrokeWidth, mSvgStrokeWidthUnit, context, mPatternWidthMapUnitScale, mSvgStrokeWidthMapUnitScale );
 
 2016   if ( !mSvgFilePath.isEmpty() )
 
 2018     map.insert( QStringLiteral( 
"svgFile" ), mSvgFilePath );
 
 2022     map.insert( QStringLiteral( 
"data" ), QString( mSvgData.toHex() ) );
 
 2025   map.insert( QStringLiteral( 
"width" ), QString::number( mPatternWidth ) );
 
 2026   map.insert( QStringLiteral( 
"angle" ), QString::number( 
mAngle ) );
 
 2031   map.insert( QStringLiteral( 
"outline_width" ), QString::number( mSvgStrokeWidth ) );
 
 2045   std::unique_ptr< QgsSVGFillSymbolLayer > clonedLayer;
 
 2046   if ( !mSvgFilePath.isEmpty() )
 
 2048     clonedLayer = qgis::make_unique< QgsSVGFillSymbolLayer >( mSvgFilePath, mPatternWidth, 
mAngle );
 
 2049     clonedLayer->setSvgFillColor( 
mColor );
 
 2050     clonedLayer->setSvgStrokeColor( mSvgStrokeColor );
 
 2051     clonedLayer->setSvgStrokeWidth( mSvgStrokeWidth );
 
 2055     clonedLayer = qgis::make_unique< QgsSVGFillSymbolLayer >( mSvgData, mPatternWidth, 
mAngle );
 
 2058   clonedLayer->setPatternWidthUnit( mPatternWidthUnit );
 
 2059   clonedLayer->setPatternWidthMapUnitScale( mPatternWidthMapUnitScale );
 
 2060   clonedLayer->setSvgStrokeWidthUnit( mSvgStrokeWidthUnit );
 
 2061   clonedLayer->setSvgStrokeWidthMapUnitScale( mSvgStrokeWidthMapUnitScale );
 
 2067     clonedLayer->setSubSymbol( 
mStroke->clone() );
 
 2071   return clonedLayer.release();
 
 2076   QDomElement symbolizerElem = doc.createElement( QStringLiteral( 
"se:PolygonSymbolizer" ) );
 
 2077   if ( !props.value( QStringLiteral( 
"uom" ), QString() ).isEmpty() )
 
 2078     symbolizerElem.setAttribute( QStringLiteral( 
"uom" ), props.value( QStringLiteral( 
"uom" ), QString() ) );
 
 2079   element.appendChild( symbolizerElem );
 
 2083   QDomElement fillElem = doc.createElement( QStringLiteral( 
"se:Fill" ) );
 
 2084   symbolizerElem.appendChild( fillElem );
 
 2086   QDomElement graphicFillElem = doc.createElement( QStringLiteral( 
"se:GraphicFill" ) );
 
 2087   fillElem.appendChild( graphicFillElem );
 
 2089   QDomElement graphicElem = doc.createElement( QStringLiteral( 
"se:Graphic" ) );
 
 2090   graphicFillElem.appendChild( graphicElem );
 
 2092   if ( !mSvgFilePath.isEmpty() )
 
 2103     symbolizerElem.appendChild( doc.createComment( QStringLiteral( 
"SVG from data not implemented yet" ) ) );
 
 2109   double angle = props.value( QStringLiteral( 
"angle" ), QStringLiteral( 
"0" ) ).toDouble( &ok );
 
 2112     angleFunc = QStringLiteral( 
"%1 + %2" ).arg( props.value( QStringLiteral( 
"angle" ), QStringLiteral( 
"0" ) ) ).arg( 
mAngle );
 
 2125     mStroke->toSld( doc, element, props );
 
 2131   QString path, mimeType;
 
 2133   Qt::PenStyle penStyle;
 
 2134   double size, strokeWidth;
 
 2136   QDomElement fillElem = element.firstChildElement( QStringLiteral( 
"Fill" ) );
 
 2137   if ( fillElem.isNull() )
 
 2140   QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral( 
"GraphicFill" ) );
 
 2141   if ( graphicFillElem.isNull() )
 
 2144   QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral( 
"Graphic" ) );
 
 2145   if ( graphicElem.isNull() )
 
 2151   if ( mimeType != QLatin1String( 
"image/svg+xml" ) )
 
 2156   QString uom = element.attribute( QStringLiteral( 
"uom" ) );
 
 2165     double d = angleFunc.toDouble( &ok );
 
 2170   std::unique_ptr< QgsSVGFillSymbolLayer > sl = qgis::make_unique< QgsSVGFillSymbolLayer >( path, size, 
angle );
 
 2171   sl->setOutputUnit( QgsUnitTypes::RenderUnit::RenderPixels );
 
 2174   sl->setSvgStrokeWidth( strokeWidth );
 
 2177   QDomElement strokeElem = element.firstChildElement( QStringLiteral( 
"Stroke" ) );
 
 2178   if ( !strokeElem.isNull() )
 
 2189   return sl.release();
 
 2207   double width = mPatternWidth;
 
 2213   QString svgFile = mSvgFilePath;
 
 2232   double strokeWidth = mSvgStrokeWidth;
 
 2239                 mSvgStrokeWidthUnit, context, mPatternWidthMapUnitScale, mSvgStrokeWidthMapUnitScale );
 
 2243 void QgsSVGFillSymbolLayer::storeViewBox()
 
 2245   if ( !mSvgData.isEmpty() )
 
 2247     QSvgRenderer r( mSvgData );
 
 2250       mSvgViewBox = r.viewBoxF();
 
 2255   mSvgViewBox = QRectF();
 
 2258 void QgsSVGFillSymbolLayer::setDefaultSvgParams()
 
 2260   if ( mSvgFilePath.isEmpty() )
 
 2265   bool hasFillParam, hasFillOpacityParam, hasStrokeParam, hasStrokeWidthParam, hasStrokeOpacityParam;
 
 2266   bool hasDefaultFillColor, hasDefaultFillOpacity, hasDefaultStrokeColor, hasDefaultStrokeWidth, hasDefaultStrokeOpacity;
 
 2267   QColor defaultFillColor, defaultStrokeColor;
 
 2268   double defaultStrokeWidth, defaultFillOpacity, defaultStrokeOpacity;
 
 2270       hasFillOpacityParam, hasDefaultFillOpacity, defaultFillOpacity,
 
 2271       hasStrokeParam, hasDefaultStrokeColor, defaultStrokeColor,
 
 2272       hasStrokeWidthParam, hasDefaultStrokeWidth, defaultStrokeWidth,
 
 2273       hasStrokeOpacityParam, hasDefaultStrokeOpacity, defaultStrokeOpacity );
 
 2275   double newFillOpacity = hasFillOpacityParam ? 
mColor.alphaF() : 1.0;
 
 2276   double newStrokeOpacity = hasStrokeOpacityParam ? mSvgStrokeColor.alphaF() : 1.0;
 
 2278   if ( hasDefaultFillColor )
 
 2280     mColor = defaultFillColor;
 
 2281     mColor.setAlphaF( newFillOpacity );
 
 2283   if ( hasDefaultFillOpacity )
 
 2285     mColor.setAlphaF( defaultFillOpacity );
 
 2287   if ( hasDefaultStrokeColor )
 
 2289     mSvgStrokeColor = defaultStrokeColor;
 
 2290     mSvgStrokeColor.setAlphaF( newStrokeOpacity );
 
 2292   if ( hasDefaultStrokeOpacity )
 
 2294     mSvgStrokeColor.setAlphaF( defaultStrokeOpacity );
 
 2296   if ( hasDefaultStrokeWidth )
 
 2298     mSvgStrokeWidth = defaultStrokeWidth;
 
 2324   return mFillLineSymbol ? mFillLineSymbol->
color() : 
mColor;
 
 2329   delete mFillLineSymbol;
 
 2344       delete mFillLineSymbol;
 
 2345       mFillLineSymbol = lineSymbol;
 
 2356   return mFillLineSymbol;
 
 2362   if ( mFillLineSymbol )
 
 2384   mDistanceUnit = unit;
 
 2385   mLineWidthUnit = unit;
 
 2392   if ( mDistanceUnit != unit || mLineWidthUnit != unit || mOffsetUnit != unit )
 
 2402   mDistanceMapUnitScale = scale;
 
 2403   mLineWidthMapUnitScale = scale;
 
 2404   mOffsetMapUnitScale = scale;
 
 2410        mDistanceMapUnitScale == mLineWidthMapUnitScale &&
 
 2411        mLineWidthMapUnitScale == mOffsetMapUnitScale )
 
 2413     return mDistanceMapUnitScale;
 
 2420   std::unique_ptr< QgsLinePatternFillSymbolLayer > patternLayer = qgis::make_unique< QgsLinePatternFillSymbolLayer >();
 
 2426   QColor 
color( Qt::black );
 
 2429   if ( 
properties.contains( QStringLiteral( 
"lineangle" ) ) )
 
 2434   else if ( 
properties.contains( QStringLiteral( 
"angle" ) ) )
 
 2438   patternLayer->setLineAngle( 
lineAngle );
 
 2440   if ( 
properties.contains( QStringLiteral( 
"distance" ) ) )
 
 2444   patternLayer->setDistance( 
distance );
 
 2446   if ( 
properties.contains( QStringLiteral( 
"linewidth" ) ) )
 
 2451   else if ( 
properties.contains( QStringLiteral( 
"outline_width" ) ) )
 
 2455   else if ( 
properties.contains( QStringLiteral( 
"line_width" ) ) )
 
 2459   patternLayer->setLineWidth( 
lineWidth );
 
 2461   if ( 
properties.contains( QStringLiteral( 
"color" ) ) )
 
 2465   else if ( 
properties.contains( QStringLiteral( 
"outline_color" ) ) )
 
 2469   else if ( 
properties.contains( QStringLiteral( 
"line_color" ) ) )
 
 2473   patternLayer->setColor( 
color );
 
 2475   if ( 
properties.contains( QStringLiteral( 
"offset" ) ) )
 
 2479   patternLayer->setOffset( 
offset );
 
 2482   if ( 
properties.contains( QStringLiteral( 
"distance_unit" ) ) )
 
 2486   if ( 
properties.contains( QStringLiteral( 
"distance_map_unit_scale" ) ) )
 
 2490   if ( 
properties.contains( QStringLiteral( 
"line_width_unit" ) ) )
 
 2494   else if ( 
properties.contains( QStringLiteral( 
"outline_width_unit" ) ) )
 
 2498   if ( 
properties.contains( QStringLiteral( 
"line_width_map_unit_scale" ) ) )
 
 2502   if ( 
properties.contains( QStringLiteral( 
"offset_unit" ) ) )
 
 2506   if ( 
properties.contains( QStringLiteral( 
"offset_map_unit_scale" ) ) )
 
 2510   if ( 
properties.contains( QStringLiteral( 
"outline_width_unit" ) ) )
 
 2514   if ( 
properties.contains( QStringLiteral( 
"outline_width_map_unit_scale" ) ) )
 
 2519   patternLayer->restoreOldDataDefinedProperties( 
properties );
 
 2521   return patternLayer.release();
 
 2526   return QStringLiteral( 
"LinePatternFill" );
 
 2529 void QgsLinePatternFillSymbolLayer::applyPattern( 
const QgsSymbolRenderContext &context, QBrush &brush, 
double lineAngle, 
double distance )
 
 2531   mBrush.setTextureImage( QImage() ); 
 
 2533   if ( !mFillLineSymbol )
 
 2538   std::unique_ptr< QgsLineSymbol > fillLineSymbol( mFillLineSymbol->
clone() );
 
 2539   if ( !fillLineSymbol )
 
 2554   outputPixelOffset = std::fmod( outputPixelOffset, outputPixelDist );
 
 2555   if ( outputPixelOffset > outputPixelDist / 2.0 )
 
 2556     outputPixelOffset -= outputPixelDist;
 
 2560   double outputPixelBleed = 0;
 
 2561   double outputPixelInterval = 0; 
 
 2562   for ( 
int i = 0; i < fillLineSymbol->symbolLayerCount(); i++ )
 
 2566     outputPixelBleed = std::max( outputPixelBleed, outputPixelLayerBleed );
 
 2569     if ( markerLineLayer )
 
 2578       outputPixelInterval = std::max( outputPixelInterval, outputPixelLayerInterval );
 
 2582   if ( outputPixelInterval > 0 )
 
 2586     double intervalScale = std::round( outputPixelInterval ) / outputPixelInterval;
 
 2587     outputPixelInterval = std::round( outputPixelInterval );
 
 2589     for ( 
int i = 0; i < fillLineSymbol->symbolLayerCount(); i++ )
 
 2594       if ( markerLineLayer )
 
 2608     height = outputPixelDist;
 
 2609     width = outputPixelInterval > 0 ? outputPixelInterval : height;
 
 2613     width = outputPixelDist;
 
 2614     height = outputPixelInterval > 0 ? outputPixelInterval : width;
 
 2618     height = outputPixelDist / std::cos( 
lineAngle * M_PI / 180 ); 
 
 2619     width = outputPixelDist / std::sin( 
lineAngle * M_PI / 180 );
 
 2622     lineAngle = 180 * std::atan2( 
static_cast< double >( height ), 
static_cast< double >( width ) ) / M_PI;
 
 2628     height = std::abs( height );
 
 2629     width = std::abs( width );
 
 2631     outputPixelDist = std::abs( height * std::cos( 
lineAngle * M_PI / 180 ) );
 
 2635     int offsetHeight = 
static_cast< int >( std::round( outputPixelOffset / std::cos( 
lineAngle * M_PI / 180 ) ) );
 
 2636     outputPixelOffset = offsetHeight * std::cos( 
lineAngle * M_PI / 180 );
 
 2645   int bufferMulti = 
static_cast< int >( std::max( std::ceil( outputPixelBleed / width ), std::ceil( outputPixelBleed / width ) ) );
 
 2649   bufferMulti = std::max( bufferMulti, 1 );
 
 2651   int xBuffer = width * bufferMulti;
 
 2652   int yBuffer = height * bufferMulti;
 
 2653   int innerWidth = width;
 
 2654   int innerHeight = height;
 
 2655   width += 2 * xBuffer;
 
 2656   height += 2 * yBuffer;
 
 2659   if ( width > 10000 || height > 10000 || width == 0 || height == 0 )
 
 2664   QImage patternImage( width, height, QImage::Format_ARGB32 );
 
 2665   patternImage.fill( 0 );
 
 2667   QPointF p1, p2, p3, p4, p5, p6;
 
 2670     p1 = QPointF( 0, yBuffer );
 
 2671     p2 = QPointF( width, yBuffer );
 
 2672     p3 = QPointF( 0, yBuffer + innerHeight );
 
 2673     p4 = QPointF( width, yBuffer + innerHeight );
 
 2677     p1 = QPointF( xBuffer, height );
 
 2678     p2 = QPointF( xBuffer, 0 );
 
 2679     p3 = QPointF( xBuffer + innerWidth, height );
 
 2680     p4 = QPointF( xBuffer + innerWidth, 0 );
 
 2684     dx = outputPixelDist * std::cos( ( 90 - 
lineAngle ) * M_PI / 180.0 );
 
 2685     dy = outputPixelDist * std::sin( ( 90 - 
lineAngle ) * M_PI / 180.0 );
 
 2686     p1 = QPointF( 0, height );
 
 2687     p2 = QPointF( width, 0 );
 
 2688     p3 = QPointF( -dx, height - dy );
 
 2689     p4 = QPointF( width - dx, -dy );
 
 2690     p5 = QPointF( dx, height + dy );
 
 2691     p6 = QPointF( width + dx, dy );
 
 2695     dx = outputPixelDist * std::cos( ( 90 - 
lineAngle ) * M_PI / 180.0 );
 
 2696     dy = outputPixelDist * std::sin( ( 90 - 
lineAngle ) * M_PI / 180.0 );
 
 2697     p1 = QPointF( width, 0 );
 
 2698     p2 = QPointF( 0, height );
 
 2699     p3 = QPointF( width - dx, -dy );
 
 2700     p4 = QPointF( -dx, height - dy );
 
 2701     p5 = QPointF( width + dx, dy );
 
 2702     p6 = QPointF( dx, height + dy );
 
 2706     dy = outputPixelDist * std::cos( ( 180 - 
lineAngle ) * M_PI / 180 );
 
 2707     dx = outputPixelDist * std::sin( ( 180 - 
lineAngle ) * M_PI / 180 );
 
 2708     p1 = QPointF( 0, 0 );
 
 2709     p2 = QPointF( width, height );
 
 2710     p5 = QPointF( dx, -dy );
 
 2711     p6 = QPointF( width + dx, height - dy );
 
 2712     p3 = QPointF( -dx, dy );
 
 2713     p4 = QPointF( width - dx, height + dy );
 
 2717     dy = outputPixelDist * std::cos( ( 180 - 
lineAngle ) * M_PI / 180 );
 
 2718     dx = outputPixelDist * std::sin( ( 180 - 
lineAngle ) * M_PI / 180 );
 
 2719     p1 = QPointF( width, height );
 
 2720     p2 = QPointF( 0, 0 );
 
 2721     p5 = QPointF( width + dx, height - dy );
 
 2722     p6 = QPointF( dx, -dy );
 
 2723     p3 = QPointF( width - dx, height + dy );
 
 2724     p4 = QPointF( -dx, dy );
 
 2731     p3 = QPointF( tempPt.x(), tempPt.y() );
 
 2733     p4 = QPointF( tempPt.x(), tempPt.y() );
 
 2735     p5 = QPointF( tempPt.x(), tempPt.y() );
 
 2737     p6 = QPointF( tempPt.x(), tempPt.y() );
 
 2741     p1 = QPointF( tempPt.x(), tempPt.y() );
 
 2743     p2 = QPointF( tempPt.x(), tempPt.y() );
 
 2746   QPainter p( &patternImage );
 
 2750   p.setRenderHint( QPainter::Antialiasing, 
false ); 
 
 2751   QPen pen( QColor( Qt::black ) );
 
 2752   pen.setWidthF( 0.1 );
 
 2753   pen.setCapStyle( Qt::FlatCap );
 
 2758   QPolygon polygon = QPolygon() << QPoint( 0, 0 ) << QPoint( width - 1, 0 ) << QPoint( width - 1, height - 1 ) << QPoint( 0, height - 1 ) << QPoint( 0, 0 );
 
 2759   p.drawPolygon( polygon );
 
 2761   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 );
 
 2762   p.drawPolygon( polygon );
 
 2768   p.setRenderHint( QPainter::Antialiasing, 
true );
 
 2779   fillLineSymbol->startRender( lineRenderContext, context.
fields() );
 
 2781   QVector<QPolygonF> polygons;
 
 2782   polygons.append( QPolygonF() << p1 << p2 );
 
 2783   polygons.append( QPolygonF() << p3 << p4 );
 
 2786     polygons.append( QPolygonF() << p5 << p6 );
 
 2789   for ( 
const QPolygonF &polygon : qgis::as_const( polygons ) )
 
 2791     fillLineSymbol->renderPolyline( polygon, context.
feature(), lineRenderContext, -1, context.
selected() );
 
 2794   fillLineSymbol->stopRender( lineRenderContext );
 
 2798   patternImage = patternImage.copy( xBuffer, yBuffer, patternImage.width() - 2 * xBuffer, patternImage.height() - 2 * yBuffer );
 
 2803     QImage transparentImage = patternImage.copy();
 
 2805     brush.setTextureImage( transparentImage );
 
 2809     brush.setTextureImage( patternImage );
 
 2812   QTransform brushTransform;
 
 2813   brush.setTransform( brushTransform );
 
 2818   applyPattern( context, 
mBrush, mLineAngle, mDistance );
 
 2820   if ( mFillLineSymbol )
 
 2828   if ( mFillLineSymbol )
 
 2837   map.insert( QStringLiteral( 
"angle" ), QString::number( mLineAngle ) );
 
 2838   map.insert( QStringLiteral( 
"distance" ), QString::number( mDistance ) );
 
 2839   map.insert( QStringLiteral( 
"line_width" ), QString::number( mLineWidth ) );
 
 2841   map.insert( QStringLiteral( 
"offset" ), QString::number( mOffset ) );
 
 2856   if ( mFillLineSymbol )
 
 2867   QDomElement symbolizerElem = doc.createElement( QStringLiteral( 
"se:PolygonSymbolizer" ) );
 
 2868   if ( !props.value( QStringLiteral( 
"uom" ), QString() ).isEmpty() )
 
 2869     symbolizerElem.setAttribute( QStringLiteral( 
"uom" ), props.value( QStringLiteral( 
"uom" ), QString() ) );
 
 2870   element.appendChild( symbolizerElem );
 
 2875   QDomElement fillElem = doc.createElement( QStringLiteral( 
"se:Fill" ) );
 
 2876   symbolizerElem.appendChild( fillElem );
 
 2878   QDomElement graphicFillElem = doc.createElement( QStringLiteral( 
"se:GraphicFill" ) );
 
 2879   fillElem.appendChild( graphicFillElem );
 
 2881   QDomElement graphicElem = doc.createElement( QStringLiteral( 
"se:Graphic" ) );
 
 2882   graphicFillElem.appendChild( graphicElem );
 
 2885   QColor lineColor = mFillLineSymbol ? mFillLineSymbol->
color() : QColor();
 
 2886   double lineWidth = mFillLineSymbol ? mFillLineSymbol->
width() : 0.0;
 
 2894   double angle = props.value( QStringLiteral( 
"angle" ), QStringLiteral( 
"0" ) ).toDouble( &ok );
 
 2897     angleFunc = QStringLiteral( 
"%1 + %2" ).arg( props.value( QStringLiteral( 
"angle" ), QStringLiteral( 
"0" ) ) ).arg( mLineAngle );
 
 2901     angleFunc = QString::number( 
angle + mLineAngle );
 
 2906   QPointF lineOffset( std::sin( mLineAngle ) * mOffset, std::cos( mLineAngle ) * mOffset );
 
 2913   QString featureStyle;
 
 2914   featureStyle.append( 
"Brush(" );
 
 2915   featureStyle.append( QStringLiteral( 
"fc:%1" ).arg( 
mColor.name() ) );
 
 2916   featureStyle.append( QStringLiteral( 
",bc:%1" ).arg( QStringLiteral( 
"#00000000" ) ) ); 
 
 2917   featureStyle.append( 
",id:\"ogr-brush-2\"" );
 
 2918   featureStyle.append( QStringLiteral( 
",a:%1" ).arg( mLineAngle ) );
 
 2919   featureStyle.append( QStringLiteral( 
",s:%1" ).arg( mLineWidth * widthScaleFactor ) );
 
 2920   featureStyle.append( 
",dx:0mm" );
 
 2921   featureStyle.append( QStringLiteral( 
",dy:%1mm" ).arg( mDistance * widthScaleFactor ) );
 
 2922   featureStyle.append( 
')' );
 
 2923   return featureStyle;
 
 2954   Qt::PenStyle lineStyle;
 
 2956   QDomElement fillElem = element.firstChildElement( QStringLiteral( 
"Fill" ) );
 
 2957   if ( fillElem.isNull() )
 
 2960   QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral( 
"GraphicFill" ) );
 
 2961   if ( graphicFillElem.isNull() )
 
 2964   QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral( 
"Graphic" ) );
 
 2965   if ( graphicElem.isNull() )
 
 2971   if ( name != QLatin1String( 
"horline" ) )
 
 2979     double d = angleFunc.toDouble( &ok );
 
 2988     offset = std::sqrt( std::pow( vectOffset.x(), 2 ) + std::pow( vectOffset.y(), 2 ) );
 
 2991   QString uom = element.attribute( QStringLiteral( 
"uom" ) );
 
 2995   std::unique_ptr< QgsLinePatternFillSymbolLayer > sl = qgis::make_unique< QgsLinePatternFillSymbolLayer >();
 
 2996   sl->setOutputUnit( QgsUnitTypes::RenderUnit::RenderPixels );
 
 2997   sl->setColor( lineColor );
 
 2999   sl->setLineAngle( 
angle );
 
 3001   sl->setDistance( size );
 
 3004   QDomElement strokeElem = element.firstChildElement( QStringLiteral( 
"Stroke" ) );
 
 3005   if ( !strokeElem.isNull() )
 
 3016   return sl.release();
 
 3093   std::unique_ptr< QgsPointPatternFillSymbolLayer > layer = qgis::make_unique< QgsPointPatternFillSymbolLayer >();
 
 3094   if ( 
properties.contains( QStringLiteral( 
"distance_x" ) ) )
 
 3096     layer->setDistanceX( 
properties[QStringLiteral( 
"distance_x" )].toDouble() );
 
 3098   if ( 
properties.contains( QStringLiteral( 
"distance_y" ) ) )
 
 3100     layer->setDistanceY( 
properties[QStringLiteral( 
"distance_y" )].toDouble() );
 
 3102   if ( 
properties.contains( QStringLiteral( 
"displacement_x" ) ) )
 
 3104     layer->setDisplacementX( 
properties[QStringLiteral( 
"displacement_x" )].toDouble() );
 
 3106   if ( 
properties.contains( QStringLiteral( 
"displacement_y" ) ) )
 
 3108     layer->setDisplacementY( 
properties[QStringLiteral( 
"displacement_y" )].toDouble() );
 
 3110   if ( 
properties.contains( QStringLiteral( 
"offset_x" ) ) )
 
 3112     layer->setOffsetX( 
properties[QStringLiteral( 
"offset_x" )].toDouble() );
 
 3114   if ( 
properties.contains( QStringLiteral( 
"offset_y" ) ) )
 
 3116     layer->setOffsetY( 
properties[QStringLiteral( 
"offset_y" )].toDouble() );
 
 3119   if ( 
properties.contains( QStringLiteral( 
"distance_x_unit" ) ) )
 
 3123   if ( 
properties.contains( QStringLiteral( 
"distance_x_map_unit_scale" ) ) )
 
 3127   if ( 
properties.contains( QStringLiteral( 
"distance_y_unit" ) ) )
 
 3131   if ( 
properties.contains( QStringLiteral( 
"distance_y_map_unit_scale" ) ) )
 
 3135   if ( 
properties.contains( QStringLiteral( 
"displacement_x_unit" ) ) )
 
 3139   if ( 
properties.contains( QStringLiteral( 
"displacement_x_map_unit_scale" ) ) )
 
 3143   if ( 
properties.contains( QStringLiteral( 
"displacement_y_unit" ) ) )
 
 3147   if ( 
properties.contains( QStringLiteral( 
"displacement_y_map_unit_scale" ) ) )
 
 3151   if ( 
properties.contains( QStringLiteral( 
"offset_x_unit" ) ) )
 
 3155   if ( 
properties.contains( QStringLiteral( 
"offset_x_map_unit_scale" ) ) )
 
 3159   if ( 
properties.contains( QStringLiteral( 
"offset_y_unit" ) ) )
 
 3163   if ( 
properties.contains( QStringLiteral( 
"offset_y_map_unit_scale" ) ) )
 
 3168   if ( 
properties.contains( QStringLiteral( 
"outline_width_unit" ) ) )
 
 3172   if ( 
properties.contains( QStringLiteral( 
"outline_width_map_unit_scale" ) ) )
 
 3177   layer->restoreOldDataDefinedProperties( 
properties );
 
 3179   return layer.release();
 
 3184   return QStringLiteral( 
"PointPatternFill" );
 
 3187 void QgsPointPatternFillSymbolLayer::applyPattern( 
const QgsSymbolRenderContext &context, QBrush &brush, 
double distanceX, 
double distanceY,
 
 3188     double displacementX, 
double displacementY, 
double offsetX, 
double offsetY )
 
 3198   if ( width > 10000 || height > 10000 ) 
 
 3201     brush.setTextureImage( img );
 
 3205   QImage patternImage( width, height, QImage::Format_ARGB32 );
 
 3206   patternImage.fill( 0 );
 
 3207   if ( patternImage.isNull() )
 
 3209     brush.setTextureImage( QImage() );
 
 3214     QPainter p( &patternImage );
 
 3224       p.setRenderHint( QPainter::Antialiasing, 
true );
 
 3234     for ( 
double currentX = -width; currentX <= width * 2.0; currentX += width )
 
 3236       for ( 
double currentY = -height; currentY <= height * 2.0; currentY += height )
 
 3245     for ( 
double currentX = -width; currentX <= width * 2.0; currentX += width )
 
 3247       for ( 
double currentY = -height / 2.0; currentY <= height * 2.0; currentY += height )
 
 3253     for ( 
double currentX = -width / 2.0; currentX <= width * 2.0; currentX += width )
 
 3255       for ( 
double currentY = -height; currentY <= height * 2.0; currentY += height / 2.0 )
 
 3257         mMarkerSymbol->
renderPoint( QPointF( currentX + widthOffset + ( std::fmod( currentY, height ) != 0 ? displacementPixelX : 0 ), currentY + heightOffset - displacementPixelY ), context.
feature(), pointRenderContext );
 
 3266     QImage transparentImage = patternImage.copy();
 
 3268     brush.setTextureImage( transparentImage );
 
 3272     brush.setTextureImage( patternImage );
 
 3274   QTransform brushTransform;
 
 3275   brush.setTransform( brushTransform );
 
 3284   if ( mRenderUsingMarkers )
 
 3302   if ( mRenderUsingMarkers )
 
 3315   if ( !mRenderUsingMarkers )
 
 3377   p->setPen( QPen( Qt::NoPen ) );
 
 3382     p->setBrush( QBrush( selColor ) );
 
 3389   path.addPolygon( points );
 
 3392     for ( 
const QPolygonF &ring : *rings )
 
 3394       path.addPolygon( ring );
 
 3397   p->setClipPath( path, Qt::IntersectClip );
 
 3399   const double left = points.boundingRect().left();
 
 3400   const double top = points.boundingRect().top();
 
 3401   const double right = points.boundingRect().right();
 
 3402   const double bottom = points.boundingRect().bottom();
 
 3409   bool alternateColumn = 
false;
 
 3410   int currentCol = -3; 
 
 3411   for ( 
double currentX = ( std::floor( left / width ) - 2 ) * width; currentX <= right + 2 * width; currentX += width, alternateColumn = !alternateColumn )
 
 3413     if ( needsExpressionContext )
 
 3416     bool alternateRow = 
false;
 
 3417     const double columnX = currentX + widthOffset;
 
 3418     int currentRow = -3;
 
 3419     for ( 
double currentY = ( std::floor( top / height ) - 2 ) * height; currentY <= bottom + 2 * height; currentY += height, alternateRow = !alternateRow )
 
 3421       double y = currentY + heightOffset;
 
 3424         x += displacementPixelX;
 
 3426       if ( !alternateColumn )
 
 3427         y -= displacementPixelY;
 
 3429       if ( needsExpressionContext )
 
 3446       for ( 
auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
 
 3457   map.insert( QStringLiteral( 
"distance_x" ), QString::number( 
mDistanceX ) );
 
 3458   map.insert( QStringLiteral( 
"distance_y" ), QString::number( 
mDistanceY ) );
 
 3459   map.insert( QStringLiteral( 
"displacement_x" ), QString::number( 
mDisplacementX ) );
 
 3460   map.insert( QStringLiteral( 
"displacement_y" ), QString::number( 
mDisplacementY ) );
 
 3461   map.insert( QStringLiteral( 
"offset_x" ), QString::number( 
mOffsetX ) );
 
 3462   map.insert( QStringLiteral( 
"offset_y" ), QString::number( 
mOffsetY ) );
 
 3496     QDomElement symbolizerElem = doc.createElement( QStringLiteral( 
"se:PolygonSymbolizer" ) );
 
 3497     if ( !props.value( QStringLiteral( 
"uom" ), QString() ).isEmpty() )
 
 3498       symbolizerElem.setAttribute( QStringLiteral( 
"uom" ), props.value( QStringLiteral( 
"uom" ), QString() ) );
 
 3499     element.appendChild( symbolizerElem );
 
 3504     QDomElement fillElem = doc.createElement( QStringLiteral( 
"se:Fill" ) );
 
 3505     symbolizerElem.appendChild( fillElem );
 
 3507     QDomElement graphicFillElem = doc.createElement( QStringLiteral( 
"se:GraphicFill" ) );
 
 3508     fillElem.appendChild( graphicFillElem );
 
 3515     symbolizerElem.appendChild( distanceElem );
 
 3521       QString errorMsg = QStringLiteral( 
"MarkerSymbolLayerV2 expected, %1 found. Skip it." ).arg( layer->
layerType() );
 
 3522       graphicFillElem.appendChild( doc.createComment( errorMsg ) );
 
 3648   std::unique_ptr< QgsCentroidFillSymbolLayer > sl = qgis::make_unique< QgsCentroidFillSymbolLayer >();
 
 3650   if ( 
properties.contains( QStringLiteral( 
"point_on_surface" ) ) )
 
 3651     sl->setPointOnSurface( 
properties[QStringLiteral( 
"point_on_surface" )].toInt() != 0 );
 
 3652   if ( 
properties.contains( QStringLiteral( 
"point_on_all_parts" ) ) )
 
 3653     sl->setPointOnAllParts( 
properties[QStringLiteral( 
"point_on_all_parts" )].toInt() != 0 );
 
 3654   if ( 
properties.contains( QStringLiteral( 
"clip_points" ) ) )
 
 3655     sl->setClipPoints( 
properties[QStringLiteral( 
"clip_points" )].toInt() != 0 );
 
 3656   if ( 
properties.contains( QStringLiteral( 
"clip_on_current_part_only" ) ) )
 
 3657     sl->setClipOnCurrentPartOnly( 
properties[QStringLiteral( 
"clip_on_current_part_only" )].toInt() != 0 );
 
 3659   sl->restoreOldDataDefinedProperties( 
properties );
 
 3661   return sl.release();
 
 3666   return QStringLiteral( 
"CentroidFill" );
 
 3697   part.exterior = points;
 
 3699     part.rings = *rings;
 
 3705     mCurrentParts << part;
 
 3717   mCurrentParts.clear();
 
 3723   render( context, mCurrentParts, feature, 
false );
 
 3726 void QgsCentroidFillSymbolLayer::render( 
QgsRenderContext &context, 
const QVector<QgsCentroidFillSymbolLayer::Part> &parts, 
const QgsFeature &feature, 
bool selected )
 
 3735   QVector< QgsGeometry > geometryParts;
 
 3736   geometryParts.reserve( parts.size() );
 
 3737   QPainterPath globalPath;
 
 3740   int maxAreaPartIdx = 0;
 
 3742   for ( 
int i = 0; i < parts.size(); i++ )
 
 3744     const Part part = parts[i];
 
 3747     if ( !geom.
isNull() && !part.rings.empty() )
 
 3749       QgsPolygon *poly = qgsgeometry_cast< QgsPolygon * >( geom.
get() );
 
 3753         int area = poly->
area();
 
 3755         if ( area > maxArea )
 
 3765       globalPath.addPolygon( part.exterior );
 
 3766       for ( 
const QPolygonF &ring : part.rings )
 
 3768         globalPath.addPolygon( ring );
 
 3773   for ( 
int i = 0; i < parts.size(); i++ )
 
 3778     const Part part = parts[i];
 
 3786         path.addPolygon( part.exterior );
 
 3787         for ( 
const QPolygonF &ring : part.rings )
 
 3789           path.addPolygon( ring );
 
 3798       context.
painter()->setClipPath( path );
 
 3802     mMarker->renderPoint( centroid, feature.
isValid() ? &feature : 
nullptr, context, -1, selected );
 
 3814   map[QStringLiteral( 
"point_on_surface" )] = QString::number( 
mPointOnSurface );
 
 3815   map[QStringLiteral( 
"point_on_all_parts" )] = QString::number( 
mPointOnAllParts );
 
 3816   map[QStringLiteral( 
"clip_points" )] = QString::number( 
mClipPoints );
 
 3823   std::unique_ptr< QgsCentroidFillSymbolLayer > x = qgis::make_unique< QgsCentroidFillSymbolLayer >();
 
 3826   x->setSubSymbol( 
mMarker->clone() );
 
 3841   mMarker->toSld( doc, element, props );
 
 3852   std::unique_ptr< QgsMarkerSymbol > marker( 
new QgsMarkerSymbol( layers ) );
 
 3854   std::unique_ptr< QgsCentroidFillSymbolLayer > sl = qgis::make_unique< QgsCentroidFillSymbolLayer >();
 
 3855   sl->setSubSymbol( marker.release() );
 
 3856   sl->setPointOnAllParts( 
false );
 
 3857   return sl.release();
 
 3884     attributes.unite( 
mMarker->usedAttributes( context ) );
 
 3902     mMarker->setOutputUnit( unit );
 
 3919     mMarker->setMapUnitScale( scale );
 
 3927     return mMarker->mapUnitScale();
 
 3937   , mImageFilePath( imageFilePath )
 
 3951   if ( 
properties.contains( QStringLiteral( 
"imageFile" ) ) )
 
 3953     imagePath = 
properties[QStringLiteral( 
"imageFile" )];
 
 3955   if ( 
properties.contains( QStringLiteral( 
"coordinate_mode" ) ) )
 
 3959   if ( 
properties.contains( QStringLiteral( 
"alpha" ) ) )
 
 3961     alpha = 
properties[QStringLiteral( 
"alpha" )].toDouble();
 
 3963   if ( 
properties.contains( QStringLiteral( 
"offset" ) ) )
 
 3967   if ( 
properties.contains( QStringLiteral( 
"angle" ) ) )
 
 3971   if ( 
properties.contains( QStringLiteral( 
"width" ) ) )
 
 3975   std::unique_ptr< QgsRasterFillSymbolLayer > symbolLayer = qgis::make_unique< QgsRasterFillSymbolLayer >( imagePath );
 
 3976   symbolLayer->setCoordinateMode( mode );
 
 3977   symbolLayer->setOpacity( alpha );
 
 3978   symbolLayer->setOffset( 
offset );
 
 3979   symbolLayer->setAngle( 
angle );
 
 3980   symbolLayer->setWidth( 
width );
 
 3981   if ( 
properties.contains( QStringLiteral( 
"offset_unit" ) ) )
 
 3985   if ( 
properties.contains( QStringLiteral( 
"offset_map_unit_scale" ) ) )
 
 3989   if ( 
properties.contains( QStringLiteral( 
"width_unit" ) ) )
 
 3993   if ( 
properties.contains( QStringLiteral( 
"width_map_unit_scale" ) ) )
 
 3998   symbolLayer->restoreOldDataDefinedProperties( 
properties );
 
 4000   return symbolLayer.release();
 
 4005   QgsStringMap::iterator it = 
properties.find( QStringLiteral( 
"imageFile" ) );
 
 4009       it.value() = pathResolver.
writePath( it.value() );
 
 4011       it.value() = pathResolver.
readPath( it.value() );
 
 4023   return QStringLiteral( 
"RasterFill" );
 
 4035   if ( !mOffset.isNull() )
 
 4041   if ( mCoordinateMode == 
Feature )
 
 4043     QRectF boundingRect = points.boundingRect();
 
 4044     mBrush.setTransform( 
mBrush.transform().translate( boundingRect.left() - 
mBrush.transform().dx(),
 
 4045                          boundingRect.top() - 
mBrush.transform().dy() ) );
 
 4049   if ( !mOffset.isNull() )
 
 4057   applyPattern( 
mBrush, mImageFilePath, mWidth, mOpacity, context );
 
 4068   map[QStringLiteral( 
"imageFile" )] = mImageFilePath;
 
 4069   map[QStringLiteral( 
"coordinate_mode" )] = QString::number( mCoordinateMode );
 
 4070   map[QStringLiteral( 
"alpha" )] = QString::number( mOpacity );
 
 4074   map[QStringLiteral( 
"angle" )] = QString::number( 
mAngle );
 
 4075   map[QStringLiteral( 
"width" )] = QString::number( mWidth );
 
 4083   std::unique_ptr< QgsRasterFillSymbolLayer > sl = qgis::make_unique< QgsRasterFillSymbolLayer >( mImageFilePath );
 
 4084   sl->setCoordinateMode( mCoordinateMode );
 
 4085   sl->setOpacity( mOpacity );
 
 4086   sl->setOffset( mOffset );
 
 4087   sl->setOffsetUnit( mOffsetUnit );
 
 4088   sl->setOffsetMapUnitScale( mOffsetMapUnitScale );
 
 4090   sl->setWidth( mWidth );
 
 4091   sl->setWidthUnit( mWidthUnit );
 
 4092   sl->setWidthMapUnitScale( mWidthMapUnitScale );
 
 4095   return sl.release();
 
 4100   return context.
convertToPainterUnits( std::max( std::fabs( mOffset.x() ), std::fabs( mOffset.y() ) ), mOffsetUnit, mOffsetMapUnitScale );
 
 4105   mImageFilePath = imagePath;
 
 4110   mCoordinateMode = mode;
 
 4128   if ( !hasWidthExpression && !hasAngleExpression && !hasOpacityExpression && !hasFileExpression )
 
 4134   if ( hasAngleExpression )
 
 4142   if ( !hasWidthExpression && !hasOpacityExpression && !hasFileExpression )
 
 4147   double width = mWidth;
 
 4148   if ( hasWidthExpression )
 
 4154   if ( hasOpacityExpression )
 
 4159   QString file = mImageFilePath;
 
 4160   if ( hasFileExpression )
 
 4168 void QgsRasterFillSymbolLayer::applyPattern( QBrush &brush, 
const QString &imageFilePath, 
const double width, 
const double alpha, 
const QgsSymbolRenderContext &context )
 
 4181       if ( size.isEmpty() )
 
 4184       size.setWidth( ( 
width * size.width() ) / 100.0 );
 
 4187       if ( 
static_cast< int >( size.width() ) < 1 || 10000.0 < size.width() )
 
 4191     size.setHeight( 0 );
 
 4199   brush.setTextureImage( img );
 
 4208   : mCountMethod( method )
 
 4209   , mPointCount( pointCount )
 
 4210   , mDensityArea( densityArea )
 
 4219   const int pointCount = 
properties.value( QStringLiteral( 
"point_count" ), QStringLiteral( 
"10" ) ).toInt();
 
 4220   const double densityArea = 
properties.value( QStringLiteral( 
"density_area" ), QStringLiteral( 
"250.0" ) ).toDouble();
 
 4222   unsigned long seed = 0;
 
 4223   if ( 
properties.contains( QStringLiteral( 
"seed" ) ) )
 
 4229     std::random_device rd;
 
 4230     std::mt19937 mt( 
seed == 0 ? rd() : 
seed );
 
 4231     std::uniform_int_distribution<> uniformDist( 1, 999999999 );
 
 4232     seed = uniformDist( mt );
 
 4237   if ( 
properties.contains( QStringLiteral( 
"density_area_unit" ) ) )
 
 4239   if ( 
properties.contains( QStringLiteral( 
"density_area_unit_scale" ) ) )
 
 4242   if ( 
properties.contains( QStringLiteral( 
"clip_points" ) ) )
 
 4244     sl->setClipPoints( 
properties[QStringLiteral( 
"clip_points" )].toInt() );
 
 4247   return sl.release();
 
 4252   return QStringLiteral( 
"RandomMarkerFill" );
 
 4257   mMarker->setColor( 
color );
 
 4263   return mMarker ? mMarker->color() : 
mColor;
 
 4268   mMarker->setOpacity( context.
opacity() );
 
 4280   part.exterior = points;
 
 4282     part.rings = *rings;
 
 4284   if ( mRenderingFeature )
 
 4288     mCurrentParts << part;
 
 4297 void QgsRandomMarkerFillSymbolLayer::render( 
QgsRenderContext &context, 
const QVector<QgsRandomMarkerFillSymbolLayer::Part> &parts, 
const QgsFeature &feature, 
bool selected )
 
 4306   QVector< QgsGeometry > geometryParts;
 
 4307   geometryParts.reserve( parts.size() );
 
 4310   for ( 
const Part &part : parts )
 
 4313     if ( !geom.
isNull() && !part.rings.empty() )
 
 4315       QgsPolygon *poly = qgsgeometry_cast< QgsPolygon * >( geom.
get() );
 
 4316       for ( 
const QPolygonF &ring : part.rings )
 
 4323       geom = geom.
buffer( 0, 0 );
 
 4325     geometryParts << geom;
 
 4329       path.addPolygon( part.exterior );
 
 4330       for ( 
const QPolygonF &ring : part.rings )
 
 4332         path.addPolygon( ring );
 
 4342     context.
painter()->setClipPath( path );
 
 4346   int count = mPointCount;
 
 4353   switch ( mCountMethod )
 
 4365       count = std::max( 0.0, std::ceil( count * ( geom.
area() / 
densityArea ) ) );
 
 4372   unsigned long seed = mSeed;
 
 4383   std::sort( randomPoints.begin(), randomPoints.end(), []( 
const QgsPointXY & a, 
const QgsPointXY & b )->bool
 
 4385     return a.y() < b.y();
 
 4393   for ( 
const QgsPointXY &p : qgis::as_const( randomPoints ) )
 
 4395     if ( needsExpressionContext )
 
 4397     mMarker->renderPoint( QPointF( p.x(), p.y() ), feature.
isValid() ? &feature : 
nullptr, context, -1, selected );
 
 4409   map.insert( QStringLiteral( 
"count_method" ), QString::number( 
static_cast< int >( mCountMethod ) ) );
 
 4410   map.insert( QStringLiteral( 
"point_count" ), QString::number( mPointCount ) );
 
 4411   map.insert( QStringLiteral( 
"density_area" ), QString::number( mDensityArea ) );
 
 4414   map.insert( QStringLiteral( 
"seed" ), QString::number( mSeed ) );
 
 4415   map.insert( QStringLiteral( 
"clip_points" ), QString::number( mClipPoints ) );
 
 4421   std::unique_ptr< QgsRandomMarkerFillSymbolLayer > res = qgis::make_unique< QgsRandomMarkerFillSymbolLayer >( mPointCount, mCountMethod, mDensityArea, mSeed );
 
 4424   res->setDensityAreaUnit( mDensityAreaUnit );
 
 4425   res->setDensityAreaUnitScale( mDensityAreaUnitScale );
 
 4426   res->mClipPoints = mClipPoints;
 
 4427   res->setSubSymbol( mMarker->clone() );
 
 4430   return res.release();
 
 4435   return mMarker.get();
 
 4447   mColor = mMarker->color();
 
 4456     attributes.unite( mMarker->usedAttributes( context ) );
 
 4465   if ( mMarker && mMarker->hasDataDefinedProperties() )
 
 4502   return mCountMethod;
 
 4507   mCountMethod = method;
 
 4512   return mDensityArea;
 
 4517   mDensityArea = area;
 
 4522   mRenderingFeature = 
true;
 
 4523   mCurrentParts.clear();
 
 4528   mRenderingFeature = 
false;
 
 4529   render( context, mCurrentParts, feature, 
false );
 
 4537     mMarker->setOutputUnit( unit );
 
 4545     return mMarker->outputUnit();
 
 4554     mMarker->setMapUnitScale( scale );
 
 4562     return mMarker->mapUnitScale();