33 #include <QSvgRenderer> 
   36 #include <QDomDocument> 
   37 #include <QDomElement> 
   44 static constexpr 
int MAX_FONT_CHARACTER_SIZE_IN_PIXELS = 500;
 
   46 static void _fixQPictureDPI( QPainter *p )
 
   52   p->scale( 
static_cast< double >( 
qt_defaultDpiX() ) / p->device()->logicalDpiX(),
 
   53             static_cast< double >( 
qt_defaultDpiY() ) / p->device()->logicalDpiY() );
 
   66   QList< Shape > shapes;
 
  165   QTransform transform;
 
  168   if ( !hasDataDefinedSize )
 
  178     const double half = scaledSize / 2.0;
 
  179     transform.scale( half, half );
 
  185     transform.rotate( 
mAngle );
 
  212   bool hasDataDefinedSize = 
false;
 
  213   const double scaledSize = 
calculateSize( context, hasDataDefinedSize );
 
  215   bool hasDataDefinedRotation = 
false;
 
  221   bool createdNewPath = 
false;
 
  228     if ( !exprVal.isNull() )
 
  239         createdNewPath = 
true;
 
  248   QTransform transform;
 
  251   transform.translate( point.x() + 
offset.x(), point.y() + 
offset.y() );
 
  254   if ( hasDataDefinedSize || createdNewPath )
 
  263     const double half = s / 2.0;
 
  264     transform.scale( half, half );
 
  269     transform.rotate( 
angle );
 
  278     polygon = transform.map( 
mPolygon );
 
  282     path = transform.map( 
mPath );
 
  284   draw( context, symbol, polygon, path );
 
  289   bool hasDataDefinedSize = 
false;
 
  290   double scaledSize = 
calculateSize( context, hasDataDefinedSize );
 
  292   bool hasDataDefinedRotation = 
false;
 
  299   QTransform transform;
 
  302   transform.translate( point.x() + 
offset.x(), point.y() + 
offset.y() );
 
  305     transform.rotate( 
angle );
 
  307   return transform.mapRect( QRectF( -scaledSize / 2.0,
 
  317   const QString cleaned = name.toLower().trimmed();
 
  319   if ( cleaned == QLatin1String( 
"square" ) || cleaned == QLatin1String( 
"rectangle" ) )
 
  321   else if ( cleaned == QLatin1String( 
"square_with_corners" ) )
 
  323   else if ( cleaned == QLatin1String( 
"diamond" ) )
 
  325   else if ( cleaned == QLatin1String( 
"pentagon" ) )
 
  327   else if ( cleaned == QLatin1String( 
"hexagon" ) )
 
  329   else if ( cleaned == QLatin1String( 
"octagon" ) )
 
  331   else if ( cleaned == QLatin1String( 
"triangle" ) )
 
  333   else if ( cleaned == QLatin1String( 
"equilateral_triangle" ) )
 
  335   else if ( cleaned == QLatin1String( 
"star" ) || cleaned == QLatin1String( 
"regular_star" ) )
 
  337   else if ( cleaned == QLatin1String( 
"arrow" ) )
 
  339   else if ( cleaned == QLatin1String( 
"circle" ) )
 
  341   else if ( cleaned == QLatin1String( 
"cross" ) )
 
  343   else if ( cleaned == QLatin1String( 
"cross_fill" ) )
 
  345   else if ( cleaned == QLatin1String( 
"cross2" ) || cleaned == QLatin1String( 
"x" ) )
 
  347   else if ( cleaned == QLatin1String( 
"line" ) )
 
  349   else if ( cleaned == QLatin1String( 
"arrowhead" ) )
 
  351   else if ( cleaned == QLatin1String( 
"filled_arrowhead" ) )
 
  353   else if ( cleaned == QLatin1String( 
"semi_circle" ) )
 
  355   else if ( cleaned == QLatin1String( 
"third_circle" ) )
 
  357   else if ( cleaned == QLatin1String( 
"quarter_circle" ) )
 
  359   else if ( cleaned == QLatin1String( 
"quarter_square" ) )
 
  361   else if ( cleaned == QLatin1String( 
"half_square" ) )
 
  363   else if ( cleaned == QLatin1String( 
"diagonal_half_square" ) )
 
  365   else if ( cleaned == QLatin1String( 
"right_half_triangle" ) )
 
  367   else if ( cleaned == QLatin1String( 
"left_half_triangle" ) )
 
  369   else if ( cleaned == QLatin1String( 
"asterisk_fill" ) )
 
  371   else if ( cleaned == QLatin1String( 
"half_arc" ) )
 
  373   else if ( cleaned == QLatin1String( 
"third_arc" ) )
 
  375   else if ( cleaned == QLatin1String( 
"quarter_arc" ) )
 
  388       return QStringLiteral( 
"square" );
 
  390       return QStringLiteral( 
"quarter_square" );
 
  392       return QStringLiteral( 
"half_square" );
 
  394       return QStringLiteral( 
"diagonal_half_square" );
 
  396       return QStringLiteral( 
"diamond" );
 
  398       return QStringLiteral( 
"pentagon" );
 
  400       return QStringLiteral( 
"hexagon" );
 
  402       return QStringLiteral( 
"octagon" );
 
  404       return QStringLiteral( 
"square_with_corners" );
 
  406       return QStringLiteral( 
"triangle" );
 
  408       return QStringLiteral( 
"equilateral_triangle" );
 
  410       return QStringLiteral( 
"left_half_triangle" );
 
  412       return QStringLiteral( 
"right_half_triangle" );
 
  414       return QStringLiteral( 
"star" );
 
  416       return QStringLiteral( 
"arrow" );
 
  418       return QStringLiteral( 
"filled_arrowhead" );
 
  420       return QStringLiteral( 
"cross_fill" );
 
  422       return QStringLiteral( 
"circle" );
 
  424       return QStringLiteral( 
"cross" );
 
  426       return QStringLiteral( 
"cross2" );
 
  428       return QStringLiteral( 
"line" );
 
  430       return QStringLiteral( 
"arrowhead" );
 
  432       return QStringLiteral( 
"semi_circle" );
 
  434       return QStringLiteral( 
"third_circle" );
 
  436       return QStringLiteral( 
"quarter_circle" );
 
  438       return QStringLiteral( 
"asterisk_fill" );
 
  440       return QStringLiteral( 
"half_arc" );
 
  442       return QStringLiteral( 
"third_arc" );
 
  444       return QStringLiteral( 
"quarter_arc" );
 
  461       polygon = QPolygonF( QRectF( QPointF( -1, -1 ), QPointF( 1, 1 ) ) );
 
  466       static constexpr 
double VERTEX_OFFSET_FROM_ORIGIN = 0.6072;
 
  468       polygon << QPointF( - VERTEX_OFFSET_FROM_ORIGIN, 1 )
 
  469               << QPointF( VERTEX_OFFSET_FROM_ORIGIN, 1 )
 
  470               << QPointF( 1, VERTEX_OFFSET_FROM_ORIGIN )
 
  471               << QPointF( 1, -VERTEX_OFFSET_FROM_ORIGIN )
 
  472               << QPointF( VERTEX_OFFSET_FROM_ORIGIN, -1 )
 
  473               << QPointF( -VERTEX_OFFSET_FROM_ORIGIN, -1 )
 
  474               << QPointF( -1, -VERTEX_OFFSET_FROM_ORIGIN )
 
  475               << QPointF( -1, VERTEX_OFFSET_FROM_ORIGIN )
 
  476               << QPointF( -VERTEX_OFFSET_FROM_ORIGIN, 1 );
 
  481       polygon = QPolygonF( QRectF( QPointF( -1, -1 ), QPointF( 0, 0 ) ) );
 
  485       polygon = QPolygonF( QRectF( QPointF( -1, -1 ), QPointF( 0, 1 ) ) );
 
  489       polygon << QPointF( -1, -1 ) << QPointF( 1, 1 ) << QPointF( -1, 1 ) << QPointF( -1, -1 );
 
  493       polygon << QPointF( -1, 0 ) << QPointF( 0, 1 )
 
  494               << QPointF( 1, 0 ) << QPointF( 0, -1 ) << QPointF( -1, 0 );
 
  504       polygon << QPointF( -0.9511, -0.3090 )
 
  505               << QPointF( -0.5878, 0.8090 )
 
  506               << QPointF( 0.5878, 0.8090 )
 
  507               << QPointF( 0.9511, -0.3090 )
 
  509               << QPointF( -0.9511, -0.3090 );
 
  520       polygon << QPointF( -0.8660, -0.5 )
 
  521               << QPointF( -0.8660, 0.5 )
 
  523               << QPointF( 0.8660, 0.5 )
 
  524               << QPointF( 0.8660, -0.5 )
 
  526               << QPointF( -0.8660, -0.5 );
 
  531       static constexpr 
double VERTEX_OFFSET_FROM_ORIGIN = 1.0 / ( 1 + M_SQRT2 );
 
  533       polygon << QPointF( - VERTEX_OFFSET_FROM_ORIGIN, 1 )
 
  534               << QPointF( VERTEX_OFFSET_FROM_ORIGIN, 1 )
 
  535               << QPointF( 1, VERTEX_OFFSET_FROM_ORIGIN )
 
  536               << QPointF( 1, -VERTEX_OFFSET_FROM_ORIGIN )
 
  537               << QPointF( VERTEX_OFFSET_FROM_ORIGIN, -1 )
 
  538               << QPointF( -VERTEX_OFFSET_FROM_ORIGIN, -1 )
 
  539               << QPointF( -1, -VERTEX_OFFSET_FROM_ORIGIN )
 
  540               << QPointF( -1, VERTEX_OFFSET_FROM_ORIGIN )
 
  541               << QPointF( -VERTEX_OFFSET_FROM_ORIGIN, 1 );
 
  546       polygon << QPointF( -1, 1 ) << QPointF( 1, 1 ) << QPointF( 0, -1 ) << QPointF( -1, 1 );
 
  554       polygon << QPointF( -0.8660, 0.5 )
 
  555               << QPointF( 0.8660, 0.5 )
 
  557               << QPointF( -0.8660, 0.5 );
 
  561       polygon << QPointF( 0, 1 ) << QPointF( 1, 1 ) << QPointF( 0, -1 ) << QPointF( 0, 1 );
 
  565       polygon << QPointF( -1, 1 ) << QPointF( 0, 1 ) << QPointF( 0, -1 ) << QPointF( -1, 1 );
 
  570       const double inner_r = std::cos( 
DEG2RAD( 72.0 ) ) / std::cos( 
DEG2RAD( 36.0 ) );
 
  572       polygon << QPointF( inner_r * std::sin( 
DEG2RAD( 324.0 ) ), - inner_r * std::cos( 
DEG2RAD( 324.0 ) ) )  
 
  573               << QPointF( std::sin( 
DEG2RAD( 288.0 ) ), - std::cos( 
DEG2RAD( 288 ) ) )    
 
  574               << QPointF( inner_r * std::sin( 
DEG2RAD( 252.0 ) ), - inner_r * std::cos( 
DEG2RAD( 252.0 ) ) )   
 
  575               << QPointF( std::sin( 
DEG2RAD( 216.0 ) ), - std::cos( 
DEG2RAD( 216.0 ) ) )   
 
  576               << QPointF( 0, inner_r )         
 
  577               << QPointF( std::sin( 
DEG2RAD( 144.0 ) ), - std::cos( 
DEG2RAD( 144.0 ) ) )   
 
  578               << QPointF( inner_r * std::sin( 
DEG2RAD( 108.0 ) ), - inner_r * std::cos( 
DEG2RAD( 108.0 ) ) )   
 
  579               << QPointF( std::sin( 
DEG2RAD( 72.0 ) ), - std::cos( 
DEG2RAD( 72.0 ) ) )    
 
  580               << QPointF( inner_r * std::sin( 
DEG2RAD( 36.0 ) ), - inner_r * std::cos( 
DEG2RAD( 36.0 ) ) )   
 
  582               << QPointF( inner_r * std::sin( 
DEG2RAD( 324.0 ) ), - inner_r * std::cos( 
DEG2RAD( 324.0 ) ) );  
 
  587       polygon << QPointF( 0, -1 )
 
  588               << QPointF( 0.5,  -0.5 )
 
  589               << QPointF( 0.25, -0.5 )
 
  590               << QPointF( 0.25,  1 )
 
  591               << QPointF( -0.25,  1 )
 
  592               << QPointF( -0.25, -0.5 )
 
  593               << QPointF( -0.5,  -0.5 )
 
  598       polygon << QPointF( 0, 0 ) << QPointF( -1, 1 ) << QPointF( -1, -1 ) << QPointF( 0, 0 );
 
  602       polygon << QPointF( -1, -0.2 )
 
  603               << QPointF( -1, -0.2 )
 
  604               << QPointF( -1, 0.2 )
 
  605               << QPointF( -0.2, 0.2 )
 
  606               << QPointF( -0.2, 1 )
 
  608               << QPointF( 0.2, 0.2 )
 
  610               << QPointF( 1, -0.2 )
 
  611               << QPointF( 0.2, -0.2 )
 
  612               << QPointF( 0.2, -1 )
 
  613               << QPointF( -0.2, -1 )
 
  614               << QPointF( -0.2, -0.2 )
 
  615               << QPointF( -1, -0.2 );
 
  620       static constexpr 
double THICKNESS = 0.3;
 
  621       static constexpr 
double HALF_THICKNESS = THICKNESS / 2.0;
 
  622       static constexpr 
double INTERSECTION_POINT = THICKNESS / M_SQRT2;
 
  623       static constexpr 
double DIAGONAL1 = M_SQRT1_2 - INTERSECTION_POINT * 0.5;
 
  624       static constexpr 
double DIAGONAL2 = M_SQRT1_2 + INTERSECTION_POINT * 0.5;
 
  626       polygon << QPointF( -HALF_THICKNESS, -1 )
 
  627               << QPointF( HALF_THICKNESS, -1 )
 
  628               << QPointF( HALF_THICKNESS, -HALF_THICKNESS - INTERSECTION_POINT )
 
  629               << QPointF( DIAGONAL1, -DIAGONAL2 )
 
  630               << QPointF( DIAGONAL2, -DIAGONAL1 )
 
  631               << QPointF( HALF_THICKNESS + INTERSECTION_POINT, -HALF_THICKNESS )
 
  632               << QPointF( 1, -HALF_THICKNESS )
 
  633               << QPointF( 1, HALF_THICKNESS )
 
  634               << QPointF( HALF_THICKNESS + INTERSECTION_POINT, HALF_THICKNESS )
 
  635               << QPointF( DIAGONAL2, DIAGONAL1 )
 
  636               << QPointF( DIAGONAL1, DIAGONAL2 )
 
  637               << QPointF( HALF_THICKNESS, HALF_THICKNESS + INTERSECTION_POINT )
 
  638               << QPointF( HALF_THICKNESS, 1 )
 
  639               << QPointF( -HALF_THICKNESS, 1 )
 
  640               << QPointF( -HALF_THICKNESS, HALF_THICKNESS + INTERSECTION_POINT )
 
  641               << QPointF( -DIAGONAL1, DIAGONAL2 )
 
  642               << QPointF( -DIAGONAL2, DIAGONAL1 )
 
  643               << QPointF( -HALF_THICKNESS - INTERSECTION_POINT, HALF_THICKNESS )
 
  644               << QPointF( -1, HALF_THICKNESS )
 
  645               << QPointF( -1, -HALF_THICKNESS )
 
  646               << QPointF( -HALF_THICKNESS - INTERSECTION_POINT, -HALF_THICKNESS )
 
  647               << QPointF( -DIAGONAL2, -DIAGONAL1 )
 
  648               << QPointF( -DIAGONAL1, -DIAGONAL2 )
 
  649               << QPointF( -HALF_THICKNESS, -HALF_THICKNESS - INTERSECTION_POINT )
 
  650               << QPointF( -HALF_THICKNESS, -1 );
 
  673   mPath = QPainterPath();
 
  679       mPath.addEllipse( QRectF( -1, -1, 2, 2 ) ); 
 
  683       mPath.arcTo( -1, -1, 2, 2, 0, 180 );
 
  684       mPath.lineTo( 0, 0 );
 
  688       mPath.arcTo( -1, -1, 2, 2, 90, 120 );
 
  689       mPath.lineTo( 0, 0 );
 
  693       mPath.arcTo( -1, -1, 2, 2, 90, 90 );
 
  694       mPath.lineTo( 0, 0 );
 
  698       mPath.moveTo( 1, 0 );
 
  699       mPath.arcTo( -1, -1, 2, 2, 0, 180 );
 
  703       mPath.moveTo( 0, -1 );
 
  704       mPath.arcTo( -1, -1, 2, 2, 90, 120 );
 
  708       mPath.moveTo( 0, -1 );
 
  709       mPath.arcTo( -1, -1, 2, 2, 90, 90 );
 
  713       mPath.moveTo( -1, 0 );
 
  714       mPath.lineTo( 1, 0 ); 
 
  715       mPath.moveTo( 0, -1 );
 
  716       mPath.lineTo( 0, 1 ); 
 
  720       mPath.moveTo( -1, -1 );
 
  721       mPath.lineTo( 1, 1 );
 
  722       mPath.moveTo( 1, -1 );
 
  723       mPath.lineTo( -1, 1 );
 
  727       mPath.moveTo( 0, -1 );
 
  728       mPath.lineTo( 0, 1 ); 
 
  732       mPath.moveTo( -1, -1 );
 
  733       mPath.lineTo( 0, 0 );
 
  734       mPath.lineTo( -1, 1 );
 
  762   double scaledSize = 
mSize;
 
  766   if ( hasDataDefinedSize )
 
  773   if ( hasDataDefinedSize && ok )
 
  778         scaledSize = std::sqrt( scaledSize );
 
  793   markerOffset( context, scaledSize, scaledSize, offsetX, offsetY );
 
  794   offset = QPointF( offsetX, offsetY );
 
  796   hasDataDefinedRotation = 
false;
 
  809     hasDataDefinedRotation = 
true;
 
  814   if ( hasDataDefinedRotation )
 
  843   , mStrokeColor( strokeColor )
 
  844   , mPenJoinStyle( penJoinStyle )
 
  861   if ( props.contains( QStringLiteral( 
"name" ) ) )
 
  865   if ( props.contains( QStringLiteral( 
"color" ) ) )
 
  867   if ( props.contains( QStringLiteral( 
"color_border" ) ) )
 
  872   else if ( props.contains( QStringLiteral( 
"outline_color" ) ) )
 
  876   else if ( props.contains( QStringLiteral( 
"line_color" ) ) )
 
  880   if ( props.contains( QStringLiteral( 
"joinstyle" ) ) )
 
  884   if ( props.contains( QStringLiteral( 
"size" ) ) )
 
  885     size = props[QStringLiteral( 
"size" )].toDouble();
 
  886   if ( props.contains( QStringLiteral( 
"angle" ) ) )
 
  887     angle = props[QStringLiteral( 
"angle" )].toDouble();
 
  888   if ( props.contains( QStringLiteral( 
"scale_method" ) ) )
 
  892   if ( props.contains( QStringLiteral( 
"offset" ) ) )
 
  894   if ( props.contains( QStringLiteral( 
"offset_unit" ) ) )
 
  896   if ( props.contains( QStringLiteral( 
"offset_map_unit_scale" ) ) )
 
  898   if ( props.contains( QStringLiteral( 
"size_unit" ) ) )
 
  900   if ( props.contains( QStringLiteral( 
"size_map_unit_scale" ) ) )
 
  903   if ( props.contains( QStringLiteral( 
"outline_style" ) ) )
 
  907   else if ( props.contains( QStringLiteral( 
"line_style" ) ) )
 
  911   if ( props.contains( QStringLiteral( 
"outline_width" ) ) )
 
  913     m->
setStrokeWidth( props[QStringLiteral( 
"outline_width" )].toDouble() );
 
  915   else if ( props.contains( QStringLiteral( 
"line_width" ) ) )
 
  917     m->
setStrokeWidth( props[QStringLiteral( 
"line_width" )].toDouble() );
 
  919   if ( props.contains( QStringLiteral( 
"outline_width_unit" ) ) )
 
  923   if ( props.contains( QStringLiteral( 
"line_width_unit" ) ) )
 
  927   if ( props.contains( QStringLiteral( 
"outline_width_map_unit_scale" ) ) )
 
  932   if ( props.contains( QStringLiteral( 
"horizontal_anchor_point" ) ) )
 
  936   if ( props.contains( QStringLiteral( 
"vertical_anchor_point" ) ) )
 
  941   if ( props.contains( QStringLiteral( 
"cap_style" ) ) )
 
  954   return QStringLiteral( 
"SimpleMarker" );
 
  961   QColor brushColor = 
mColor;
 
  967   mBrush = QBrush( brushColor );
 
  968   mPen = QPen( penColor );
 
  978     selBrushColor.setAlphaF( context.
opacity() );
 
  979     selPenColor.setAlphaF( context.
opacity() );
 
  998     mCachedOpacity = context.
opacity();
 
 1004     mSelPen.setColor( selBrushColor );
 
 1036     scaledSize = ( std::abs( std::sin( 
mAngle * M_PI / 180 ) ) + std::abs( std::cos( 
mAngle * M_PI / 180 ) ) ) * scaledSize;
 
 1039   const double pw = 
static_cast< int >( std::round( ( ( 
qgsDoubleNear( 
mPen.widthF(), 0.0 ) ? 1 : 
mPen.widthF() * 4 ) + 1 ) ) ) / 2 * 2; 
 
 1040   const int imageSize = ( 
static_cast< int >( scaledSize ) + pw ) / 2 * 2 + 1; 
 
 1041   const double center = imageSize / 2.0;
 
 1047   mCache = QImage( QSize( imageSize, imageSize ), QImage::Format_ARGB32_Premultiplied );
 
 1054   p.setRenderHint( QPainter::Antialiasing );
 
 1055   p.setBrush( needsBrush ? 
mBrush : Qt::NoBrush );
 
 1057   p.translate( QPointF( center, center ) );
 
 1065   mSelCache = QImage( QSize( imageSize, imageSize ), QImage::Format_ARGB32_Premultiplied );
 
 1069   p.setRenderHint( QPainter::Antialiasing );
 
 1070   p.setBrush( needsBrush ? 
mSelBrush : Qt::NoBrush );
 
 1072   p.translate( QPointF( center, center ) );
 
 1083     p.setRenderHint( QPainter::Antialiasing );
 
 1084     p.fillRect( 0, 0, imageSize, imageSize, selColor );
 
 1085     p.setBrush( needsBrush ? 
mBrush : Qt::NoBrush );
 
 1087     p.translate( QPointF( center, center ) );
 
 1106   QColor brushColor = 
mColor;
 
 1107   brushColor.setAlphaF( brushColor.alphaF() * context.
opacity() );
 
 1108   mBrush.setColor( brushColor );
 
 1111   penColor.setAlphaF( penColor.alphaF() * context.
opacity() );
 
 1112   mPen.setColor( penColor );
 
 1121       c.setAlphaF( 
c.alphaF() * context.
opacity() );
 
 1131       c.setAlphaF( 
c.alphaF() * context.
opacity() );
 
 1183     p->setBrush( Qt::NoBrush );
 
 1187   if ( !polygon.isEmpty() )
 
 1188     p->drawPolygon( polygon );
 
 1190     p->drawPath( path );
 
 1207     const double s = img.width();
 
 1209     bool hasDataDefinedSize = 
false;
 
 1210     const double scaledSize = 
calculateSize( context, hasDataDefinedSize );
 
 1212     bool hasDataDefinedRotation = 
false;
 
 1217     p->drawImage( QRectF( point.x() - s / 2.0 + 
offset.x(),
 
 1218                           point.y() - s / 2.0 + 
offset.y(),
 
 1233   map[QStringLiteral( 
"size" )] = QString::number( 
mSize );
 
 1236   map[QStringLiteral( 
"angle" )] = QString::number( 
mAngle );
 
 1242   map[QStringLiteral( 
"outline_width" )] = QString::number( 
mStrokeWidth );
 
 1275   QDomElement graphicElem = doc.createElement( QStringLiteral( 
"se:Graphic" ) );
 
 1276   element.appendChild( graphicElem );
 
 1285   const double angle = props.value( QStringLiteral( 
"angle" ), QStringLiteral( 
"0" ) ).toDouble( &ok );
 
 1288     angleFunc = QStringLiteral( 
"%1 + %2" ).arg( props.value( QStringLiteral( 
"angle" ), QStringLiteral( 
"0" ) ).toString() ).arg( 
mAngle );
 
 1303   Q_UNUSED( mmScaleFactor )
 
 1304   Q_UNUSED( mapUnitScaleFactor )
 
 1306   QString ogrType = 
"3"; 
 
 1307   if ( mName == 
"square" )
 
 1311   else if ( mName == 
"triangle" )
 
 1315   else if ( mName == 
"star" )
 
 1319   else if ( mName == 
"circle" )
 
 1323   else if ( mName == 
"cross" )
 
 1327   else if ( mName == 
"x" || mName == 
"cross2" )
 
 1331   else if ( mName == 
"line" )
 
 1337   ogrString.append( 
"SYMBOL(" );
 
 1338   ogrString.append( 
"id:" );
 
 1339   ogrString.append( 
'\"' );
 
 1340   ogrString.append( 
"ogr-sym-" );
 
 1341   ogrString.append( ogrType );
 
 1342   ogrString.append( 
'\"' );
 
 1343   ogrString.append( 
",c:" );
 
 1344   ogrString.append( 
mColor.name() );
 
 1345   ogrString.append( 
",o:" );
 
 1347   ogrString.append( QString( 
",s:%1mm" ).arg( 
mSize ) );
 
 1348   ogrString.append( 
')' );
 
 1353   ogrString.append( 
"PEN(" );
 
 1354   ogrString.append( 
"c:" );
 
 1355   ogrString.append( 
mColor.name() );
 
 1356   ogrString.append( 
",w:" );
 
 1357   ogrString.append( QString::number( 
mSize ) );
 
 1358   ogrString.append( 
"mm" );
 
 1359   ogrString.append( 
")" );
 
 1367   QDomElement graphicElem = element.firstChildElement( QStringLiteral( 
"Graphic" ) );
 
 1368   if ( graphicElem.isNull() )
 
 1371   QString name = QStringLiteral( 
"square" );
 
 1384     const double d = angleFunc.toDouble( &ok );
 
 1394   const QString uom = element.attribute( QStringLiteral( 
"uom" ) );
 
 1420     p->drawPath( 
mPath );
 
 1433   if ( hasDataDefinedSize )
 
 1454     size *= mmMapUnitScaleFactor;
 
 1461   const double halfSize = 
size / 2.0;
 
 1478   QColor pc = 
mPen.color();
 
 1479   QColor bc = 
mBrush.color();
 
 1499   QPointF off( offsetX, offsetY );
 
 1528   t.translate( shift.x() + off.x(), shift.y() - off.y() );
 
 1536     t.scale( halfSize, -halfSize );
 
 1538     polygon = t.map( polygon );
 
 1541     p.reserve( polygon.size() );
 
 1542     for ( 
int i = 0; i < polygon.size(); i++ )
 
 1547     if ( 
mBrush.style() != Qt::NoBrush )
 
 1549     if ( 
mPen.style() != Qt::NoPen )
 
 1554     shift += QPointF( off.x(), -off.y() );
 
 1555     if ( 
mBrush.style() != Qt::NoBrush )
 
 1557     if ( 
mPen.style() != Qt::NoPen )
 
 1562     const QPointF pt1 = t.map( QPointF( 0, -halfSize ) );
 
 1563     const QPointF pt2 = t.map( QPointF( 0, halfSize ) );
 
 1565     if ( 
mPen.style() != Qt::NoPen )
 
 1570     if ( 
mPen.style() != Qt::NoPen )
 
 1572       const QPointF pt1 = t.map( QPointF( -halfSize, 0 ) );
 
 1573       const QPointF pt2 = t.map( QPointF( halfSize, 0 ) );
 
 1574       const QPointF pt3 = t.map( QPointF( 0, -halfSize ) );
 
 1575       const QPointF pt4 = t.map( QPointF( 0, halfSize ) );
 
 1583     if ( 
mPen.style() != Qt::NoPen )
 
 1585       const QPointF pt1 = t.map( QPointF( -halfSize, -halfSize ) );
 
 1586       const QPointF pt2 = t.map( QPointF( halfSize, halfSize ) );
 
 1587       const QPointF pt3 = t.map( QPointF( halfSize, -halfSize ) );
 
 1588       const QPointF pt4 = t.map( QPointF( -halfSize, halfSize ) );
 
 1596     if ( 
mPen.style() != Qt::NoPen )
 
 1598       const QPointF pt1 = t.map( QPointF( -halfSize, halfSize ) );
 
 1599       const QPointF pt2 = t.map( QPointF( 0, 0 ) );
 
 1600       const QPointF pt3 = t.map( QPointF( -halfSize, -halfSize ) );
 
 1686   symbolBounds.adjust( -penWidth / 2.0, -penWidth / 2.0,
 
 1687                        penWidth / 2.0, penWidth / 2.0 );
 
 1689   return symbolBounds;
 
 1738   if ( props.contains( QStringLiteral( 
"name" ) ) )
 
 1739     name = props[QStringLiteral( 
"name" )].toString();
 
 1740   if ( props.contains( QStringLiteral( 
"size" ) ) )
 
 1741     size = props[QStringLiteral( 
"size" )].toDouble();
 
 1742   if ( props.contains( QStringLiteral( 
"angle" ) ) )
 
 1743     angle = props[QStringLiteral( 
"angle" )].toDouble();
 
 1744   if ( props.contains( QStringLiteral( 
"scale_method" ) ) )
 
 1748   if ( props.contains( QStringLiteral( 
"offset" ) ) )
 
 1750   if ( props.contains( QStringLiteral( 
"offset_unit" ) ) )
 
 1752   if ( props.contains( QStringLiteral( 
"offset_map_unit_scale" ) ) )
 
 1754   if ( props.contains( QStringLiteral( 
"size_unit" ) ) )
 
 1756   if ( props.contains( QStringLiteral( 
"size_map_unit_scale" ) ) )
 
 1758   if ( props.contains( QStringLiteral( 
"horizontal_anchor_point" ) ) )
 
 1762   if ( props.contains( QStringLiteral( 
"vertical_anchor_point" ) ) )
 
 1776   return QStringLiteral( 
"FilledMarker" );
 
 1801   map[QStringLiteral( 
"size" )] = QString::number( 
mSize );
 
 1804   map[QStringLiteral( 
"angle" )] = QString::number( 
mAngle );
 
 1860     attr.unite( mFill->usedAttributes( context ) );
 
 1868   if ( mFill && mFill->hasDataDefinedProperties() )
 
 1877     mFill->setColor( 
c );
 
 1882   return mFill ?  mFill->color() : 
mColor;
 
 1889          || ( mFill && mFill->usesMapUnits() );
 
 1903   const double prevOpacity = mFill->opacity();
 
 1904   mFill->setOpacity( mFill->opacity() * context.
opacity() );
 
 1908     p->setBrush( Qt::red );
 
 1912     p->setBrush( Qt::NoBrush );
 
 1914   p->setPen( Qt::black );
 
 1919   if ( !polygon.isEmpty() )
 
 1925     const QPolygonF poly = path.toFillPolygon();
 
 1931   mFill->setOpacity( prevOpacity );
 
 1946   mColor = QColor( 35, 35, 35 );
 
 1960   if ( props.contains( QStringLiteral( 
"name" ) ) )
 
 1961     name = props[QStringLiteral( 
"name" )].toString();
 
 1962   if ( props.contains( QStringLiteral( 
"size" ) ) )
 
 1963     size = props[QStringLiteral( 
"size" )].toDouble();
 
 1964   if ( props.contains( QStringLiteral( 
"angle" ) ) )
 
 1965     angle = props[QStringLiteral( 
"angle" )].toDouble();
 
 1966   if ( props.contains( QStringLiteral( 
"scale_method" ) ) )
 
 1971   if ( props.contains( QStringLiteral( 
"size_unit" ) ) )
 
 1973   if ( props.contains( QStringLiteral( 
"size_map_unit_scale" ) ) )
 
 1975   if ( props.contains( QStringLiteral( 
"fixedAspectRatio" ) ) )
 
 1977   if ( props.contains( QStringLiteral( 
"offset" ) ) )
 
 1979   if ( props.contains( QStringLiteral( 
"offset_unit" ) ) )
 
 1981   if ( props.contains( QStringLiteral( 
"offset_map_unit_scale" ) ) )
 
 1983   if ( props.contains( QStringLiteral( 
"fill" ) ) )
 
 1988   else if ( props.contains( QStringLiteral( 
"color" ) ) )
 
 1992   if ( props.contains( QStringLiteral( 
"outline" ) ) )
 
 1997   else if ( props.contains( QStringLiteral( 
"outline_color" ) ) )
 
 2001   else if ( props.contains( QStringLiteral( 
"line_color" ) ) )
 
 2006   if ( props.contains( QStringLiteral( 
"outline-width" ) ) )
 
 2009     m->
setStrokeWidth( props[QStringLiteral( 
"outline-width" )].toDouble() );
 
 2011   else if ( props.contains( QStringLiteral( 
"outline_width" ) ) )
 
 2013     m->
setStrokeWidth( props[QStringLiteral( 
"outline_width" )].toDouble() );
 
 2015   else if ( props.contains( QStringLiteral( 
"line_width" ) ) )
 
 2017     m->
setStrokeWidth( props[QStringLiteral( 
"line_width" )].toDouble() );
 
 2020   if ( props.contains( QStringLiteral( 
"outline_width_unit" ) ) )
 
 2024   else if ( props.contains( QStringLiteral( 
"line_width_unit" ) ) )
 
 2028   if ( props.contains( QStringLiteral( 
"outline_width_map_unit_scale" ) ) )
 
 2031   if ( props.contains( QStringLiteral( 
"horizontal_anchor_point" ) ) )
 
 2035   if ( props.contains( QStringLiteral( 
"vertical_anchor_point" ) ) )
 
 2044   if ( props.contains( QStringLiteral( 
"parameters" ) ) )
 
 2046     const QVariantMap 
parameters = props[QStringLiteral( 
"parameters" )].toMap();
 
 2055   const QVariantMap::iterator it = 
properties.find( QStringLiteral( 
"name" ) );
 
 2074   QColor defaultFillColor, defaultStrokeColor;
 
 2076   bool hasFillOpacityParam = 
false, hasStrokeParam = 
false, hasStrokeWidthParam = 
false, hasStrokeOpacityParam = 
false;
 
 2077   bool hasDefaultFillColor = 
false, hasDefaultFillOpacity = 
false, hasDefaultStrokeColor = 
false, hasDefaultStrokeWidth = 
false, hasDefaultStrokeOpacity = 
false;
 
 2079       hasFillOpacityParam, hasDefaultFillOpacity, fillOpacity,
 
 2080       hasStrokeParam, hasDefaultStrokeColor, defaultStrokeColor,
 
 2081       hasStrokeWidthParam, hasDefaultStrokeWidth, 
strokeWidth,
 
 2082       hasStrokeOpacityParam, hasDefaultStrokeOpacity, strokeOpacity );
 
 2084   const double newFillOpacity = hasFillOpacityParam ? 
fillColor().alphaF() : 1.0;
 
 2085   const double newStrokeOpacity = hasStrokeOpacityParam ? 
strokeColor().alphaF() : 1.0;
 
 2087   if ( hasDefaultFillColor )
 
 2089     defaultFillColor.setAlphaF( newFillOpacity );
 
 2092   if ( hasDefaultFillOpacity )
 
 2095     c.setAlphaF( fillOpacity );
 
 2098   if ( hasDefaultStrokeColor )
 
 2100     defaultStrokeColor.setAlphaF( newStrokeOpacity );
 
 2103   if ( hasDefaultStrokeWidth )
 
 2107   if ( hasDefaultStrokeOpacity )
 
 2110     c.setAlphaF( strokeOpacity );
 
 2124     const double widthScaleFactor = 3.465;
 
 2127     mDefaultAspectRatio = svgViewbox.isValid() ? svgViewbox.height() / svgViewbox.width() : 0.0;
 
 2135   if ( aPreservedAspectRatio && !par )
 
 2139   else if ( !aPreservedAspectRatio && par )
 
 2154   return QStringLiteral( 
"SvgMarker" );
 
 2174   bool hasDataDefinedSize = 
false;
 
 2175   const double scaledWidth = calculateSize( context, hasDataDefinedSize );
 
 2179   if ( 
static_cast< int >( width ) < 1 || 10000.0 < width )
 
 2186   bool hasDataDefinedAspectRatio = 
false;
 
 2187   const double aspectRatio = 
calculateAspectRatio( context, scaledWidth, hasDataDefinedAspectRatio );
 
 2230       scaledHeight = svgViewbox.isValid() ? scaledWidth * svgViewbox.height() / svgViewbox.width() : scaledWidth;
 
 2234   QPointF outputOffset;
 
 2236   calculateOffsetAndRotation( context, scaledWidth, scaledHeight, outputOffset, 
angle );
 
 2238   p->translate( point + outputOffset );
 
 2244   bool fitsInCache = 
true;
 
 2245   bool usePict = 
true;
 
 2252     if ( fitsInCache && img.width() > 1 )
 
 2262         QImage transparentImage = img.copy();
 
 2264         p->drawImage( -transparentImage.width() / 2.0, -transparentImage.height() / 2.0, transparentImage );
 
 2268         p->drawImage( -img.width() / 2.0, -img.height() / 2.0, img );
 
 2273   if ( usePict || !fitsInCache )
 
 2275     p->setOpacity( context.
opacity() );
 
 2279     if ( pct.width() > 1 )
 
 2282       _fixQPictureDPI( p );
 
 2283       p->drawPicture( 0, 0, pct );
 
 2291 double QgsSvgMarkerSymbolLayer::calculateSize( 
QgsSymbolRenderContext &context, 
bool &hasDataDefinedSize )
 const 
 2293   double scaledSize = 
mSize;
 
 2297   if ( hasDataDefinedSize )
 
 2305     if ( hasDataDefinedSize )
 
 2312   if ( hasDataDefinedSize && ok )
 
 2317         scaledSize = std::sqrt( scaledSize );
 
 2330   if ( !hasDataDefinedAspectRatio )
 
 2340   const double defaultHeight = 
mSize * scaledAspectRatio;
 
 2341   scaledAspectRatio = defaultHeight / scaledSize;
 
 2344   double scaledHeight = scaledSize * scaledAspectRatio;
 
 2351   if ( hasDataDefinedAspectRatio && ok )
 
 2356         scaledHeight = sqrt( scaledHeight );
 
 2363   scaledAspectRatio = scaledHeight / scaledSize;
 
 2365   return scaledAspectRatio;
 
 2368 void QgsSvgMarkerSymbolLayer::calculateOffsetAndRotation( 
QgsSymbolRenderContext &context, 
double scaledWidth, 
double scaledHeight, QPointF &offset, 
double &
angle )
 const 
 2373   markerOffset( context, scaledWidth, scaledHeight, offsetX, offsetY );
 
 2374   offset = QPointF( offsetX, offsetY );
 
 2384   if ( hasDataDefinedRotation )
 
 2410   map[QStringLiteral( 
"name" )] = 
mPath;
 
 2411   map[QStringLiteral( 
"size" )] = QString::number( 
mSize );
 
 2414   map[QStringLiteral( 
"fixedAspectRatio" )] = QString::number( 
mFixedAspectRatio );
 
 2415   map[QStringLiteral( 
"angle" )] = QString::number( 
mAngle );
 
 2422   map[QStringLiteral( 
"outline_width" )] = QString::number( 
mStrokeWidth );
 
 2497   QDomElement graphicElem = doc.createElement( QStringLiteral( 
"se:Graphic" ) );
 
 2498   element.appendChild( graphicElem );
 
 2508   const double angle = props.value( QStringLiteral( 
"angle" ), QStringLiteral( 
"0" ) ).toDouble( &ok );
 
 2511     angleFunc = QStringLiteral( 
"%1 + %2" ).arg( props.value( QStringLiteral( 
"angle" ), QStringLiteral( 
"0" ) ).toString() ).arg( 
mAngle );
 
 2529   QDomElement graphicElem = element.firstChildElement( QStringLiteral( 
"Graphic" ) );
 
 2530   if ( graphicElem.isNull() )
 
 2533   QString 
path, mimeType;
 
 2540   const QString uom = element.attribute( QStringLiteral( 
"uom" ) );
 
 2543   if ( mimeType != QLatin1String( 
"image/svg+xml" ) )
 
 2551     const double d = angleFunc.toDouble( &ok );
 
 2577   if ( hasDataDefinedSize )
 
 2583   if ( hasDataDefinedSize && ok )
 
 2597     size *= mmMapUnitScaleFactor;
 
 2611   const double offsetX = 
offset.x();
 
 2612   const double offsetY = 
offset.y();
 
 2614   QPointF outputOffset( offsetX, offsetY );
 
 2664   QSvgRenderer r( svgContent );
 
 2671   QSizeF outSize( r.defaultSize() );
 
 2672   outSize.scale( 
size, 
size, Qt::KeepAspectRatio );
 
 2678     p.translate( r.defaultSize().width() / 2.0, r.defaultSize().height() / 2.0 );
 
 2680     p.translate( -r.defaultSize().width() / 2.0, -r.defaultSize().height() / 2.0 );
 
 2682   pd.
setShift( shift + QPointF( outputOffset.x(), -outputOffset.y() ) );
 
 2683   pd.
setOutputSize( QRectF( -outSize.width() / 2.0, -outSize.height() / 2.0, outSize.width(), outSize.height() ) );
 
 2692   bool hasDataDefinedSize = 
false;
 
 2693   double scaledWidth = calculateSize( context, hasDataDefinedSize );
 
 2695   bool hasDataDefinedAspectRatio = 
false;
 
 2696   const double aspectRatio = 
calculateAspectRatio( context, scaledWidth, hasDataDefinedAspectRatio );
 
 2703   if ( 
static_cast< int >( scaledWidth ) < 1 || 10000.0 < scaledWidth )
 
 2708   QPointF outputOffset;
 
 2710   calculateOffsetAndRotation( context, scaledWidth, scaledHeight, outputOffset, 
angle );
 
 2749       scaledHeight = svgViewbox.isValid() ? scaledWidth * svgViewbox.height() / svgViewbox.width() : scaledWidth;
 
 2753   QTransform transform;
 
 2755   transform.translate( point.x() + outputOffset.x(), point.y() + outputOffset.y() );
 
 2758     transform.rotate( 
angle );
 
 2763   QRectF symbolBounds = transform.mapRect( QRectF( -scaledWidth / 2.0,
 
 2764                         -scaledHeight / 2.0,
 
 2772   return symbolBounds;
 
 2796   if ( props.contains( QStringLiteral( 
"imageFile" ) ) )
 
 2797     path = props[QStringLiteral( 
"imageFile" )].toString();
 
 2798   if ( props.contains( QStringLiteral( 
"size" ) ) )
 
 2799     size = props[QStringLiteral( 
"size" )].toDouble();
 
 2800   if ( props.contains( QStringLiteral( 
"angle" ) ) )
 
 2801     angle = props[QStringLiteral( 
"angle" )].toDouble();
 
 2802   if ( props.contains( QStringLiteral( 
"scale_method" ) ) )
 
 2807   if ( props.contains( QStringLiteral( 
"alpha" ) ) )
 
 2809     m->
setOpacity( props[QStringLiteral( 
"alpha" )].toDouble() );
 
 2812   if ( props.contains( QStringLiteral( 
"size_unit" ) ) )
 
 2814   if ( props.contains( QStringLiteral( 
"size_map_unit_scale" ) ) )
 
 2816   if ( props.contains( QStringLiteral( 
"fixedAspectRatio" ) ) )
 
 2819   if ( props.contains( QStringLiteral( 
"offset" ) ) )
 
 2821   if ( props.contains( QStringLiteral( 
"offset_unit" ) ) )
 
 2823   if ( props.contains( QStringLiteral( 
"offset_map_unit_scale" ) ) )
 
 2826   if ( props.contains( QStringLiteral( 
"horizontal_anchor_point" ) ) )
 
 2830   if ( props.contains( QStringLiteral( 
"vertical_anchor_point" ) ) )
 
 2843   const QVariantMap::iterator it = 
properties.find( QStringLiteral( 
"name" ) );
 
 2844   if ( it != 
properties.end() && it.value().type() == QVariant::String )
 
 2862   if ( aPreservedAspectRatio && !par )
 
 2866   else if ( !aPreservedAspectRatio && par )
 
 2885   return QStringLiteral( 
"RasterMarker" );
 
 2901   if ( 
path.isEmpty() )
 
 2905   double height = 0.0;
 
 2907   bool hasDataDefinedSize = 
false;
 
 2908   const double scaledSize = calculateSize( context, hasDataDefinedSize );
 
 2910   bool hasDataDefinedAspectRatio = 
false;
 
 2911   const double aspectRatio = 
calculateAspectRatio( context, scaledSize, hasDataDefinedAspectRatio );
 
 2913   QPointF outputOffset;
 
 2920     if ( 
size.isEmpty() )
 
 2923     width = ( scaledSize * 
static_cast< double >( 
size.width() ) ) / 100.0;
 
 2924     height = ( scaledSize * 
static_cast< double >( 
size.height() ) ) / 100.0;
 
 2927     if ( 
static_cast< int >( width ) < 1 || 10000.0 < width || 
static_cast< int >( height ) < 1 || 10000.0 < height )
 
 2930     calculateOffsetAndRotation( context, width, height, outputOffset, 
angle );
 
 2940       if ( !
size.isNull() && 
size.isValid() && 
size.width() > 0 )
 
 2942         height = width * ( 
static_cast< double >( 
size.height() ) / 
static_cast< double >( 
size.width() ) );
 
 2947     if ( 
static_cast< int >( width ) < 1 || 10000.0 < width )
 
 2950     calculateOffsetAndRotation( context, scaledSize, scaledSize * ( height / width ), outputOffset, 
angle );
 
 2954   p->translate( point + outputOffset );
 
 2970   if ( !img.isNull() )
 
 2977     const bool prevSmoothTransform = p->testRenderHint( QPainter::RenderHint::SmoothPixmapTransform );
 
 2978     p->setRenderHint( QPainter::RenderHint::SmoothPixmapTransform, 
true );
 
 2979     p->drawImage( -img.width() / 2.0, -img.height() / 2.0, img );
 
 2980     p->setRenderHint( QPainter::RenderHint::SmoothPixmapTransform, prevSmoothTransform );
 
 2984 double QgsRasterMarkerSymbolLayer::calculateSize( 
QgsSymbolRenderContext &context, 
bool &hasDataDefinedSize )
 const 
 2986   double scaledSize = 
mSize;
 
 2990   if ( hasDataDefinedSize )
 
 2998     if ( hasDataDefinedSize )
 
 3005   if ( hasDataDefinedSize && ok )
 
 3010         scaledSize = std::sqrt( scaledSize );
 
 3023   if ( !hasDataDefinedAspectRatio )
 
 3033   const double defaultHeight = 
mSize * scaledAspectRatio;
 
 3034   scaledAspectRatio = defaultHeight / scaledSize;
 
 3037   double scaledHeight = scaledSize * scaledAspectRatio;
 
 3044   if ( hasDataDefinedAspectRatio && ok )
 
 3049         scaledHeight = sqrt( scaledHeight );
 
 3056   scaledAspectRatio = scaledHeight / scaledSize;
 
 3058   return scaledAspectRatio;
 
 3061 void QgsRasterMarkerSymbolLayer::calculateOffsetAndRotation( 
QgsSymbolRenderContext &context, 
double scaledWidth, 
double scaledHeight, QPointF &offset, 
double &
angle )
 const 
 3066   markerOffset( context, scaledWidth, scaledHeight, offsetX, offsetY );
 
 3067   offset = QPointF( offsetX, offsetY );
 
 3077   if ( hasDataDefinedRotation )
 
 3098   map[QStringLiteral( 
"imageFile" )] = 
mPath;
 
 3099   map[QStringLiteral( 
"size" )] = QString::number( 
mSize );
 
 3102   map[QStringLiteral( 
"fixedAspectRatio" )] = QString::number( 
mFixedAspectRatio );
 
 3103   map[QStringLiteral( 
"angle" )] = QString::number( 
mAngle );
 
 3104   map[QStringLiteral( 
"alpha" )] = QString::number( 
mOpacity );
 
 3149   bool hasDataDefinedSize = 
false;
 
 3150   const double scaledSize = calculateSize( context, hasDataDefinedSize );
 
 3152   bool hasDataDefinedAspectRatio = 
false;
 
 3153   const double aspectRatio = 
calculateAspectRatio( context, scaledSize, hasDataDefinedAspectRatio );
 
 3157   if ( 
static_cast< int >( scaledSize ) < 1 || 10000.0 < scaledSize )
 
 3162   QPointF outputOffset;
 
 3164   calculateOffsetAndRotation( context, scaledSize, scaledSize * ( height / width ), outputOffset, 
angle );
 
 3166   QTransform transform;
 
 3169   transform.translate( point.x() + outputOffset.x(), point.y() + outputOffset.y() );
 
 3172     transform.rotate( 
angle );
 
 3174   QRectF symbolBounds = transform.mapRect( QRectF( -width / 2.0,
 
 3179   return symbolBounds;
 
 3191   mOrigSize = pointSize;
 
 3212   if ( props.contains( QStringLiteral( 
"font" ) ) )
 
 3213     fontFamily = props[QStringLiteral( 
"font" )].toString();
 
 3214   if ( props.contains( QStringLiteral( 
"chr" ) ) && props[QStringLiteral( 
"chr" )].toString().length() > 0 )
 
 3215     string = props[QStringLiteral( 
"chr" )].toString();
 
 3216   if ( props.contains( QStringLiteral( 
"size" ) ) )
 
 3217     pointSize = props[QStringLiteral( 
"size" )].toDouble();
 
 3218   if ( props.contains( QStringLiteral( 
"color" ) ) )
 
 3220   if ( props.contains( QStringLiteral( 
"angle" ) ) )
 
 3221     angle = props[QStringLiteral( 
"angle" )].toDouble();
 
 3225   if ( props.contains( QStringLiteral( 
"font_style" ) ) )
 
 3226     m->
setFontStyle( props[QStringLiteral( 
"font_style" )].toString() );
 
 3227   if ( props.contains( QStringLiteral( 
"outline_color" ) ) )
 
 3229   if ( props.contains( QStringLiteral( 
"outline_width" ) ) )
 
 3230     m->
setStrokeWidth( props[QStringLiteral( 
"outline_width" )].toDouble() );
 
 3231   if ( props.contains( QStringLiteral( 
"offset" ) ) )
 
 3233   if ( props.contains( QStringLiteral( 
"offset_unit" ) ) )
 
 3235   if ( props.contains( QStringLiteral( 
"offset_map_unit_scale" ) ) )
 
 3237   if ( props.contains( QStringLiteral( 
"size_unit" ) ) )
 
 3239   if ( props.contains( QStringLiteral( 
"size_map_unit_scale" ) ) )
 
 3241   if ( props.contains( QStringLiteral( 
"outline_width_unit" ) ) )
 
 3243   if ( props.contains( QStringLiteral( 
"outline_width_map_unit_scale" ) ) )
 
 3245   if ( props.contains( QStringLiteral( 
"joinstyle" ) ) )
 
 3247   if ( props.contains( QStringLiteral( 
"horizontal_anchor_point" ) ) )
 
 3249   if ( props.contains( QStringLiteral( 
"vertical_anchor_point" ) ) )
 
 3259   return QStringLiteral( 
"FontMarker" );
 
 3264   QColor brushColor = 
mColor;
 
 3265   QColor penColor = mStrokeColor;
 
 3267   brushColor.setAlphaF( 
mColor.alphaF() * context.
opacity() );
 
 3268   penColor.setAlphaF( mStrokeColor.alphaF() * context.
opacity() );
 
 3270   mBrush = QBrush( brushColor );
 
 3271   mPen = QPen( penColor );
 
 3272   mPen.setJoinStyle( mPenJoinStyle );
 
 3275   mFont = QFont( mFontFamily );
 
 3276   if ( !mFontStyle.isEmpty() )
 
 3284   if ( mNonZeroFontSize && sizePixels > MAX_FONT_CHARACTER_SIZE_IN_PIXELS )
 
 3289     mFontSizeScale = sizePixels / MAX_FONT_CHARACTER_SIZE_IN_PIXELS;
 
 3290     sizePixels = MAX_FONT_CHARACTER_SIZE_IN_PIXELS;
 
 3293     mFontSizeScale = 1.0;
 
 3297   mFont.setPixelSize( std::max( 2, 
static_cast< int >( std::round( sizePixels ) ) ) );
 
 3298   mFontMetrics.reset( 
new QFontMetrics( mFont ) );
 
 3299   mChrWidth = mFontMetrics->horizontalAdvance( mString );
 
 3300   mChrOffset = QPointF( mChrWidth / 2.0, -mFontMetrics->ascent() / 2.0 );
 
 3307   if ( mUseCachedPath )
 
 3309     QPointF chrOffset = mChrOffset;
 
 3311     const QString charToRender = characterToRender( context, chrOffset, chrWidth );
 
 3312     mCachedPath = QPainterPath();
 
 3313     mCachedPath.addText( -chrOffset.x(), -chrOffset.y(), mFont, charToRender );
 
 3322 QString QgsFontMarkerSymbolLayer::characterToRender( 
QgsSymbolRenderContext &context, QPointF &charOffset, 
double &charWidth )
 
 3324   charOffset = mChrOffset;
 
 3325   QString stringToRender = mString;
 
 3330     if ( stringToRender != mString )
 
 3332       charWidth = mFontMetrics->horizontalAdvance( stringToRender );
 
 3333       charOffset = QPointF( charWidth / 2.0, -mFontMetrics->ascent() / 2.0 );
 
 3336   return stringToRender;
 
 3341     bool &hasDataDefinedRotation,
 
 3343     double &
angle )
 const 
 3348   markerOffset( context, scaledSize, scaledSize, offsetX, offsetY );
 
 3349   offset = QPointF( offsetX, offsetY );
 
 3365   if ( hasDataDefinedRotation )
 
 3389   double scaledSize = 
mSize;
 
 3393   if ( hasDataDefinedSize )
 
 3399   if ( hasDataDefinedSize && ok )
 
 3404         scaledSize = std::sqrt( scaledSize );
 
 3416   if ( !p || !mNonZeroFontSize )
 
 3419   QTransform transform;
 
 3422   QColor brushColor = 
mColor;
 
 3431     brushColor.setAlphaF( brushColor.alphaF() * context.
opacity() );
 
 3433   mBrush.setColor( brushColor );
 
 3435   QColor penColor = mStrokeColor;
 
 3441   penColor.setAlphaF( penColor.alphaF() * context.
opacity() );
 
 3465   p->setBrush( mBrush );
 
 3468     mPen.setColor( penColor );
 
 3469     mPen.setWidthF( penWidth );
 
 3474     p->setPen( Qt::NoPen );
 
 3481     mFont.setFamily( ok ? 
fontFamily : mFontFamily );
 
 3491     mFontMetrics.reset( 
new QFontMetrics( mFont ) );
 
 3494   QPointF chrOffset = mChrOffset;
 
 3496   const QString charToRender = characterToRender( context, chrOffset, chrWidth );
 
 3498   const double sizeToRender = calculateSize( context );
 
 3500   bool hasDataDefinedRotation = 
false;
 
 3503   calculateOffsetAndRotation( context, sizeToRender, hasDataDefinedRotation, 
offset, 
angle );
 
 3505   p->translate( point.x() + 
offset.x(), point.y() + 
offset.y() );
 
 3508     transform.rotate( 
angle );
 
 3512     const double s = sizeToRender / mOrigSize;
 
 3513     transform.scale( s, s );
 
 3517     transform.scale( mFontSizeScale, mFontSizeScale );
 
 3519   if ( mUseCachedPath )
 
 3521     p->drawPath( transform.map( mCachedPath ) );
 
 3526     path.addText( -chrOffset.x(), -chrOffset.y(), mFont, charToRender );
 
 3527     p->drawPath( transform.map( path ) );
 
 3534   props[QStringLiteral( 
"font" )] = mFontFamily;
 
 3535   props[QStringLiteral( 
"font_style" )] = mFontStyle;
 
 3536   props[QStringLiteral( 
"chr" )] = mString;
 
 3537   props[QStringLiteral( 
"size" )] = QString::number( 
mSize );
 
 3542   props[QStringLiteral( 
"outline_width" )] = QString::number( mStrokeWidth );
 
 3546   props[QStringLiteral( 
"angle" )] = QString::number( 
mAngle );
 
 3579   QDomElement graphicElem = doc.createElement( QStringLiteral( 
"se:Graphic" ) );
 
 3580   element.appendChild( graphicElem );
 
 3582   const QString fontPath = QStringLiteral( 
"ttf://%1" ).arg( mFontFamily );
 
 3583   int markIndex = !mString.isEmpty() ? mString.at( 0 ).unicode() : 0;
 
 3590   const double angle = props.value( QStringLiteral( 
"angle" ), QStringLiteral( 
"0" ) ).toDouble( &ok );
 
 3593     angleFunc = QStringLiteral( 
"%1 + %2" ).arg( props.value( QStringLiteral( 
"angle" ), QStringLiteral( 
"0" ) ).toString() ).arg( 
mAngle );
 
 3615   QPointF chrOffset = mChrOffset;
 
 3616   double chrWidth = mChrWidth;
 
 3618   ( void )characterToRender( context, chrOffset, chrWidth );
 
 3620   if ( !mFontMetrics )
 
 3621     mFontMetrics.reset( 
new QFontMetrics( mFont ) );
 
 3623   double scaledSize = calculateSize( context );
 
 3626     chrWidth *= scaledSize / mOrigSize;
 
 3628   chrWidth *= mFontSizeScale;
 
 3630   bool hasDataDefinedRotation = 
false;
 
 3633   calculateOffsetAndRotation( context, scaledSize, hasDataDefinedRotation, 
offset, 
angle );
 
 3636   QTransform transform;
 
 3639   transform.translate( point.x() + 
offset.x(), point.y() + 
offset.y() );
 
 3642     transform.rotate( 
angle );
 
 3644   QRectF symbolBounds = transform.mapRect( QRectF( -chrWidth / 2.0,
 
 3648   return symbolBounds;
 
 3655   QDomElement graphicElem = element.firstChildElement( QStringLiteral( 
"Graphic" ) );
 
 3656   if ( graphicElem.isNull() )
 
 3659   QString name, format;
 
 3667   if ( !name.startsWith( QLatin1String( 
"ttf://" ) ) || format != QLatin1String( 
"ttf" ) )
 
 3677     const double d = angleFunc.toDouble( &ok );
 
 3685   const QString uom = element.attribute( QStringLiteral( 
"uom" ) );
 
 3708   QMap<QString, QgsProperty>::iterator it = 
mParameters.begin();
 
 3720   QMap<QString, QgsProperty>::const_iterator it = 
mParameters.constBegin();
 
 3723     attrs.unite( it.value().referencedFields( context.
expressionContext(), 
true ) );
 
@ DynamicRotation
Rotation of symbol may be changed during rendering and symbol should not be cached.
ScaleMethod
Scale methods.
@ ScaleDiameter
Calculate scale by the diameter.
@ ScaleArea
Calculate scale by the area.
@ 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,...
@ RenderBlocking
Render and load remote sources in the same thread to ensure rendering remote sources (svg and images)...
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.
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...
Exports QGIS layers to the DXF format.
void writeFilledCircle(const QString &layer, const QColor &color, const QgsPoint &pt, double radius)
Write filled circle (as hatch)
void writeCircle(const QString &layer, const QColor &color, const QgsPoint &pt, double radius, const QString &lineStyleName, double width)
Write circle (as polyline)
void writeLine(const QgsPoint &pt1, const QgsPoint &pt2, const QString &layer, const QString &lineStyleName, const QColor &color, double width=-1)
Write line (as a polyline)
static double mapUnitScaleFactor(double scale, QgsUnitTypes::RenderUnit symbolUnits, QgsUnitTypes::DistanceUnit mapUnits, double mapUnitsPerPixel=1.0)
Returns scale factor for conversion to map units.
QgsUnitTypes::DistanceUnit mapUnits() const
Retrieve map units.
void writePolygon(const QgsRingSequence &polygon, const QString &layer, const QString &hatchPattern, const QColor &color)
Draw dxf filled polygon (HATCH)
double symbologyScale() const
Returns the reference scale for output.
void clipValueToMapUnitScale(double &value, const QgsMapUnitScale &scale, double pixelToMMFactor) const
Clips value to scale minimum/maximum.
void writePolyline(const QgsPointSequence &line, const QString &layer, const QString &lineStyleName, const QColor &color, double width=-1)
Draw dxf primitives (LWPOLYLINE)
A paint device for drawing into dxf files.
void setShift(QPointF shift)
void setLayer(const QString &layer)
void setOutputSize(const QRectF &r)
void setDrawingSize(QSizeF size)
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool hasGeometry() const
Returns true if the feature has an associated geometry.
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
static QgsFillSymbol * createSimple(const QVariantMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties.
Filled marker symbol layer, consisting of a shape which is rendered using a QgsFillSymbol.
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...
QColor color() const override
The fill color.
QgsFilledMarkerSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
bool hasDataDefinedProperties() const override
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
QgsSymbol * subSymbol() override
Returns the symbol's sub symbol, if present.
~QgsFilledMarkerSymbolLayer() override
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
double estimateMaxBleed(const QgsRenderContext &context) const override
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
void setColor(const QColor &c) override
The fill color.
QString layerType() const override
Returns a string that represents this layer type.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsFilledMarkerSymbolLayer.
QgsFilledMarkerSymbolLayer(QgsSimpleMarkerSymbolLayerBase::Shape shape=Circle, double size=DEFAULT_SIMPLEMARKER_SIZE, double angle=DEFAULT_SIMPLEMARKER_ANGLE, Qgis::ScaleMethod scaleMethod=DEFAULT_SCALE_METHOD)
Constructor for QgsFilledMarkerSymbolLayer.
~QgsFontMarkerSymbolLayer() override
void setStrokeColor(const QColor &color) override
Set stroke color.
QgsFontMarkerSymbolLayer(const QString &fontFamily=DEFAULT_FONTMARKER_FONT, QString chr=DEFAULT_FONTMARKER_CHR, double pointSize=DEFAULT_FONTMARKER_SIZE, const QColor &color=DEFAULT_FONTMARKER_COLOR, double angle=DEFAULT_FONTMARKER_ANGLE)
Constructs a font marker symbol layer.
void setStrokeWidthMapUnitScale(const QgsMapUnitScale &scale)
Sets the stroke width map unit scale.
double strokeWidth() const
Returns the marker's stroke width.
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void renderPoint(QPointF point, QgsSymbolRenderContext &context) override
Renders a marker at the specified point.
void setFontStyle(const QString &style)
Sets the font style for the font which will be used to render the point.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
QString fontStyle() const
Returns the font style for the associated font which will be used to render the point.
QString fontFamily() const
Returns the font family name for the associated font which will be used to render the point.
void setStrokeWidthUnit(QgsUnitTypes::RenderUnit unit)
Sets the stroke width unit.
QRectF bounds(QPointF point, QgsSymbolRenderContext &context) override
Returns the approximate bounding box of the marker symbol layer, taking into account any data defined...
void writeSldMarker(QDomDocument &doc, QDomElement &element, const QVariantMap &props) const override
Writes the symbol layer definition as a SLD XML element.
void setStrokeWidth(double width)
Set's the marker's stroke width.
static void resolveFonts(const QVariantMap &properties, const QgsReadWriteContext &context)
Resolves fonts from a properties map, raising warnings in the specified context if the required fonts...
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
void setPenJoinStyle(Qt::PenJoinStyle style)
Sets the stroke join style.
static QgsSymbolLayer * createFromSld(QDomElement &element)
Creates a new QgsFontMarkerSymbolLayer from an SLD XML element.
QgsFontMarkerSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
QString layerType() const override
Returns a string that represents this layer type.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsFontMarkerSymbolLayer from a property map (see properties())
static QString translateNamedStyle(const QString &namedStyle)
Returns the localized named style of a font, if such a translation is available.
static bool fontFamilyMatchOnSystem(const QString &family, QString *chosen=nullptr, bool *match=nullptr)
Check whether font family is on system.
static bool updateFontViaStyle(QFont &f, const QString &fontstyle, bool fallback=false)
Updates font with named style and retain all font properties.
QgsWkbTypes::GeometryType type
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, bool *isMissing=nullptr)
Returns the specified path rendered as an image.
static void adjustHueSaturation(QImage &image, double saturation, const QColor &colorizeColor=QColor(), double colorizeStrength=1.0, QgsFeedback *feedback=nullptr)
Alter the hue or saturation of a QImage.
Perform transforms between map coordinates and device coordinates.
double mapUnitsPerPixel() const
Returns the current map units per pixel.
double mapRotation() const
Returns the current map rotation in degrees (clockwise).
Struct for storing maximum and minimum scales for measurements in map units.
Abstract base class for marker symbol layers.
QPointF offset() const
Returns the marker's offset, which is the horizontal and vertical displacement which the rendered mar...
double mLineAngle
Line rotation angle (see setLineAngle() for details)
HorizontalAnchorPoint
Symbol horizontal anchor points.
void setAngle(double angle)
Sets the rotation angle for the marker.
Qgis::ScaleMethod scaleMethod() const
Returns the method to use for scaling the marker's size.
QgsUnitTypes::RenderUnit mOffsetUnit
Offset units.
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the symbol's size.
void setVerticalAnchorPoint(VerticalAnchorPoint v)
Sets the vertical anchor point for positioning the symbol.
void setOutputUnit(QgsUnitTypes::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
QPointF mOffset
Marker offset.
void setHorizontalAnchorPoint(HorizontalAnchorPoint h)
Sets the horizontal anchor point for positioning the symbol.
QgsMapUnitScale mapUnitScale() const override
void setOffset(QPointF offset)
Sets the marker's offset, which is the horizontal and vertical displacement which the rendered marker...
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the symbol's size.
double size() const
Returns the symbol size.
QgsMapUnitScale mOffsetMapUnitScale
Offset map unit scale.
HorizontalAnchorPoint mHorizontalAnchorPoint
Horizontal anchor point.
static QPointF _rotatedOffset(QPointF offset, double angle)
Adjusts a marker offset to account for rotation.
Qgis::ScaleMethod mScaleMethod
Marker size scaling method.
QgsMapUnitScale mSizeMapUnitScale
Marker size map unit scale.
VerticalAnchorPoint
Symbol vertical anchor points.
void markerOffset(QgsSymbolRenderContext &context, double &offsetX, double &offsetY) const
Calculates the required marker offset, including both the symbol offset and any displacement required...
VerticalAnchorPoint mVerticalAnchorPoint
Vertical anchor point.
QgsUnitTypes::RenderUnit mSizeUnit
Marker size unit.
void setOffsetUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the symbol's offset.
void setOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the symbol's offset.
double mAngle
Marker rotation angle, in degrees clockwise from north.
QgsUnitTypes::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
double angle() const
Returns the rotation angle for the marker, in degrees clockwise from north.
void setMapUnitScale(const QgsMapUnitScale &scale) override
Resolves relative paths into absolute paths and vice versa.
Point geometry type, with support for z-dimension and m-values.
QVariant value(int key, const QgsExpressionContext &context, const QVariant &defaultValue=QVariant()) const override
Returns the calculated value of the property with the specified key from within the collection.
bool isActive(int key) const override
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.
Raster marker symbol layer class.
double mFixedAspectRatio
The marker fixed aspect ratio.
QRectF bounds(QPointF point, QgsSymbolRenderContext &context) override
Returns the approximate bounding box of the marker symbol layer, taking into account any data defined...
void renderPoint(QPointF point, QgsSymbolRenderContext &context) override
Renders a marker at the specified point.
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
QgsMapUnitScale mapUnitScale() const override
void setOpacity(double opacity)
Set the marker opacity.
QString path() const
Returns the marker raster image path.
double calculateAspectRatio(QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedAspectRatio) const
Calculates the marker aspect ratio between width and height.
QgsRasterMarkerSymbolLayer(const QString &path=QString(), double size=DEFAULT_SVGMARKER_SIZE, double angle=DEFAULT_SVGMARKER_ANGLE, Qgis::ScaleMethod scaleMethod=DEFAULT_SCALE_METHOD)
Constructs raster marker symbol layer with picture from given absolute path to a raster image file.
void setPath(const QString &path)
Set the marker raster image path.
double defaultAspectRatio() const
Returns the default marker aspect ratio between width and height, 0 if not yet calculated.
void setFixedAspectRatio(double ratio)
Set the marker aspect ratio between width and height to be used in rendering, if the value set is low...
void setMapUnitScale(const QgsMapUnitScale &scale) override
QgsRasterMarkerSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
bool preservedAspectRatio() const
Returns the preserved aspect ratio value, true if fixed aspect ratio has been lower or equal to 0.
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.
~QgsRasterMarkerSymbolLayer() override
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a raster marker symbol layer from a string map of properties.
double mOpacity
The marker default opacity.
double updateDefaultAspectRatio()
Calculates the default marker aspect ratio between width and height.
double mDefaultAspectRatio
The marker default aspect ratio.
bool setPreservedAspectRatio(bool par)
Set preserved the marker aspect ratio between width and height.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
QString layerType() const override
Returns a string that represents this layer type.
double opacity() const
Returns the marker opacity.
The class is used as a container of context for various read/write operations on other objects.
void pushMessage(const QString &message, Qgis::MessageLevel level=Qgis::MessageLevel::Warning) const
Append a message to the context.
Contains information about the context of a rendering operation.
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
QPainter * painter()
Returns the destination QPainter for the render operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
bool forceVectorOutput() const
Returns true if rendering operations should use vector operations instead of any faster raster shortc...
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
QColor selectionColor() const
Returns the color to use when rendering selected features.
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly during rendering to check if rendering shou...
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...
Scoped object for saving and restoring a QPainter object's state.
Abstract base class for simple marker symbol layers.
void renderPoint(QPointF point, QgsSymbolRenderContext &context) override
Renders a marker at the specified point.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
Shape mShape
Symbol shape.
void calculateOffsetAndRotation(QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedRotation, QPointF &offset, double &angle) const
Calculates the marker offset and rotation.
bool prepareMarkerShape(Shape shape)
Prepares the layer for drawing the specified shape (QPolygonF version)
QPainterPath mPath
Painter path representing shape. If mPolygon is empty then the shape is stored in mPath.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
static bool shapeIsFilled(QgsSimpleMarkerSymbolLayerBase::Shape shape)
Returns true if a symbol shape has a fill.
static QList< QgsSimpleMarkerSymbolLayerBase::Shape > availableShapes()
Returns a list of all available shape types.
QgsSimpleMarkerSymbolLayerBase::Shape shape() const
Returns the shape for the rendered marker symbol.
~QgsSimpleMarkerSymbolLayerBase() override
bool shapeToPolygon(Shape shape, QPolygonF &polygon) const
Creates a polygon representing the specified shape.
bool prepareMarkerPath(Shape symbol)
Prepares the layer for drawing the specified shape (QPainterPath version)
QPolygonF mPolygon
Polygon of points in shape. If polygon is empty then shape is using mPath.
QRectF bounds(QPointF point, QgsSymbolRenderContext &context) override
Returns the approximate bounding box of the marker symbol layer, taking into account any data defined...
QgsSimpleMarkerSymbolLayerBase(QgsSimpleMarkerSymbolLayerBase::Shape shape=Circle, double size=DEFAULT_SIMPLEMARKER_SIZE, double angle=DEFAULT_SIMPLEMARKER_ANGLE, Qgis::ScaleMethod scaleMethod=DEFAULT_SCALE_METHOD)
Constructor for QgsSimpleMarkerSymbolLayerBase.
static QgsSimpleMarkerSymbolLayerBase::Shape decodeShape(const QString &name, bool *ok=nullptr)
Attempts to decode a string representation of a shape name to the corresponding shape.
static QString encodeShape(QgsSimpleMarkerSymbolLayerBase::Shape shape)
Encodes a shape to its string representation.
double calculateSize(QgsSymbolRenderContext &context, bool &hasDataDefinedSize) const
Calculates the desired size of the marker, considering data defined size overrides.
Shape
Marker symbol shapes.
@ ArrowHead
Right facing arrow head (unfilled, lines only)
@ QuarterArc
A line-only one quarter arc (since QGIS 3.20)
@ Octagon
Octagon (since QGIS 3.18)
@ ThirdCircle
One third circle (top left third)
@ CrossFill
Solid filled cross.
@ RightHalfTriangle
Right half of triangle.
@ SquareWithCorners
A square with diagonal corners (since QGIS 3.18)
@ LeftHalfTriangle
Left half of triangle.
@ QuarterSquare
Quarter square (top left quarter)
@ ArrowHeadFilled
Right facing filled arrow head.
@ Cross2
Rotated cross (lines only), "x" shape.
@ Cross
Cross (lines only)
@ EquilateralTriangle
Equilateral triangle.
@ HalfSquare
Half square (left half)
@ ThirdArc
A line-only one third arc (since QGIS 3.20)
@ QuarterCircle
Quarter circle (top left quarter)
@ SemiCircle
Semi circle (top half)
@ DiagonalHalfSquare
Diagonal half square (bottom left half)
@ AsteriskFill
A filled asterisk shape (since QGIS 3.18)
@ HalfArc
A line-only half arc (since QGIS 3.20)
Simple marker symbol layer, consisting of a rendered shape with solid fill color and an stroke.
QPen mSelPen
QPen to use as stroke of selected symbols.
void setStrokeWidthUnit(QgsUnitTypes::RenderUnit u)
Sets the unit for the width of the marker's stroke.
void setColor(const QColor &color) override
The fill color.
QColor mStrokeColor
Stroke color.
QImage mSelCache
Cached image of selected marker, if using cached version.
QImage mCache
Cached image of marker, if using cached version.
QBrush mSelBrush
QBrush to use as fill of selected symbols.
void setFillColor(const QColor &color) override
Set fill color.
Qt::PenJoinStyle penJoinStyle() const
Returns the marker's stroke join style (e.g., miter, bevel, etc).
QgsUnitTypes::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
void drawMarker(QPainter *p, QgsSymbolRenderContext &context)
Draws the marker shape in the specified painter.
QPen mPen
QPen corresponding to marker's stroke style.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsSimpleMarkerSymbolLayer.
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
QRectF bounds(QPointF point, QgsSymbolRenderContext &context) override
Returns the approximate bounding box of the marker symbol layer, taking into account any data defined...
void setMapUnitScale(const QgsMapUnitScale &scale) override
QColor color() const override
The fill color.
QgsMapUnitScale mapUnitScale() const override
Qt::PenStyle mStrokeStyle
Stroke style.
QgsSimpleMarkerSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
static QgsSymbolLayer * createFromSld(QDomElement &element)
Creates a new QgsSimpleMarkerSymbolLayer from an SLD XML element.
QgsSimpleMarkerSymbolLayer(QgsSimpleMarkerSymbolLayerBase::Shape shape=Circle, double size=DEFAULT_SIMPLEMARKER_SIZE, double angle=DEFAULT_SIMPLEMARKER_ANGLE, Qgis::ScaleMethod scaleMethod=DEFAULT_SCALE_METHOD, const QColor &color=DEFAULT_SIMPLEMARKER_COLOR, const QColor &strokeColor=DEFAULT_SIMPLEMARKER_BORDERCOLOR, Qt::PenJoinStyle penJoinStyle=DEFAULT_SIMPLEMARKER_JOINSTYLE)
Constructor for QgsSimpleMarkerSymbolLayer.
~QgsSimpleMarkerSymbolLayer() override
Qt::PenCapStyle mPenCapStyle
Stroke pen cap style.
void setOutputUnit(QgsUnitTypes::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
QString layerType() const override
Returns a string that represents this layer type.
double mStrokeWidth
Stroke width.
void setStrokeWidthMapUnitScale(const QgsMapUnitScale &scale)
Sets the map scale for the width of the marker's stroke.
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
void setStrokeStyle(Qt::PenStyle strokeStyle)
Sets the marker's stroke style (e.g., solid, dashed, etc)
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
QColor fillColor() const override
Gets fill color.
QColor strokeColor() const override
Returns the marker's stroke color.
QBrush mBrush
QBrush corresponding to marker's fill style.
void setStrokeWidth(double w)
Sets the width of the marker's stroke.
void setStrokeColor(const QColor &color) override
Sets the marker's stroke color.
Qt::PenStyle strokeStyle() const
Returns the marker's stroke style (e.g., solid, dashed, etc)
QgsUnitTypes::RenderUnit mStrokeWidthUnit
Stroke width units.
bool mUsingCache
true if using cached images of markers for drawing.
void setPenCapStyle(Qt::PenCapStyle style)
Sets the marker's stroke cap style (e.g., flat, round, etc).
bool writeDxf(QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, QgsSymbolRenderContext &context, QPointF shift=QPointF(0.0, 0.0)) const override
write as DXF
void writeSldMarker(QDomDocument &doc, QDomElement &element, const QVariantMap &props) const override
Writes the symbol layer definition as a SLD XML element.
static const int MAXIMUM_CACHE_WIDTH
Maximum width/height of cache image.
QString ogrFeatureStyle(double mmScaleFactor, double mapUnitScaleFactor) const override
bool prepareCache(QgsSymbolRenderContext &context)
Prepares cache image.
QgsMapUnitScale mStrokeWidthMapUnitScale
Stroke width map unit scale.
double strokeWidth() const
Returns the width of the marker's stroke.
Qt::PenJoinStyle mPenJoinStyle
Stroke pen join style.
void renderPoint(QPointF point, QgsSymbolRenderContext &context) override
Renders a marker at the specified point.
QSizeF svgViewboxSize(const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, double fixedAspectRatio=0, bool blocking=false, const QMap< QString, QString > ¶meters=QMap< QString, QString >())
Calculates the viewbox size of a (possibly cached) SVG file.
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.
QByteArray svgContent(const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, double fixedAspectRatio=0, bool blocking=false, const QMap< QString, QString > ¶meters=QMap< QString, QString >(), bool *isMissingImage=nullptr)
Gets the SVG content corresponding to the given path.
QgsSvgMarkerSymbolLayer * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
QColor fillColor() const override
Gets fill color.
QgsMapUnitScale mapUnitScale() const override
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns the set of attributes referenced by the layer.
static QgsSymbolLayer * create(const QVariantMap &properties=QVariantMap())
Creates the symbol.
double mDefaultAspectRatio
The marker default aspect ratio.
QgsUnitTypes::RenderUnit mStrokeWidthUnit
QString layerType() const override
Returns a string that represents this layer type.
void setStrokeWidthMapUnitScale(const QgsMapUnitScale &scale)
void setOutputUnit(QgsUnitTypes::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
QString path() const
Returns the marker SVG path.
QgsUnitTypes::RenderUnit outputUnit() const override
Returns the units to use for sizes and widths within the symbol layer.
bool preservedAspectRatio() const
Returns the preserved aspect ratio value, true if fixed aspect ratio has been lower or equal to 0.
void stopRender(QgsSymbolRenderContext &context) override
Called after a set of rendering operations has finished on the supplied render context.
void setStrokeWidth(double w)
void prepareExpressions(const QgsSymbolRenderContext &context) override
Prepares all data defined property expressions for evaluation.
QMap< QString, QgsProperty > mParameters
bool setPreservedAspectRatio(bool par)
Set preserved the marker aspect ratio between width and height.
QVariantMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void setStrokeWidthUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the stroke width.
double calculateAspectRatio(QgsSymbolRenderContext &context, double scaledSize, bool &hasDataDefinedAspectRatio) const
Calculates the marker aspect ratio between width and height.
bool usesMapUnits() const override
Returns true if the symbol layer has any components which use map unit based sizes.
static QgsSymbolLayer * createFromSld(QDomElement &element)
void setStrokeColor(const QColor &c) override
Set stroke color.
void setMapUnitScale(const QgsMapUnitScale &scale) override
double updateDefaultAspectRatio()
Calculates the default marker aspect ratio between width and height.
QColor strokeColor() const override
Gets stroke color.
void setFillColor(const QColor &color) override
Set fill color.
QRectF bounds(QPointF point, QgsSymbolRenderContext &context) override
Returns the approximate bounding box of the marker symbol layer, taking into account any data defined...
double strokeWidth() const
QMap< QString, QgsProperty > parameters() const
Returns the dynamic SVG parameters.
QgsSvgMarkerSymbolLayer(const QString &path, double size=DEFAULT_SVGMARKER_SIZE, double angle=DEFAULT_SVGMARKER_ANGLE, Qgis::ScaleMethod scaleMethod=DEFAULT_SCALE_METHOD)
Constructs SVG marker symbol layer with picture from given absolute path to a SVG file.
void writeSldMarker(QDomDocument &doc, QDomElement &element, const QVariantMap &props) const override
Writes the symbol layer definition as a SLD XML element.
void renderPoint(QPointF point, QgsSymbolRenderContext &context) override
Renders a marker at the specified point.
~QgsSvgMarkerSymbolLayer() override
void startRender(QgsSymbolRenderContext &context) override
Called before a set of rendering operations commences on the supplied render context.
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.
QgsMapUnitScale mStrokeWidthMapUnitScale
void setParameters(const QMap< QString, QgsProperty > ¶meters)
Sets the dynamic SVG parameters.
double mFixedAspectRatio
The marker fixed aspect ratio.
bool writeDxf(QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, QgsSymbolRenderContext &context, QPointF shift=QPointF(0.0, 0.0)) const override
write as DXF
void setFixedAspectRatio(double ratio)
Set the marker aspect ratio between width and height to be used in rendering, if the value set is low...
void setPath(const QString &path)
Set the marker SVG path.
static bool externalMarkerFromSld(QDomElement &element, QString &path, QString &format, int &markIndex, QColor &color, double &size)
static bool rotationFromSldElement(QDomElement &element, QString &rotationFunc)
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 QColor decodeColor(const QString &str)
static QString svgSymbolPathToName(const QString &path, const QgsPathResolver &pathResolver)
Determines an SVG symbol's name from its path.
static QPointF toPoint(const QVariant &value, bool *ok=nullptr)
Converts a value to a point.
static double rescaleUom(double size, QgsUnitTypes::RenderUnit unit, const QVariantMap &props)
Rescales the given size based on the uomScale found in the props, if any is found,...
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 Qt::PenCapStyle decodePenCapStyle(const QString &str)
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 Qgis::ScaleMethod decodeScaleMethod(const QString &str)
Decodes a symbol scale method from a string.
static QString encodePenCapStyle(Qt::PenCapStyle style)
static void externalMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &path, const QString &format, int *markIndex=nullptr, const QColor &color=QColor(), double size=-1)
static double sizeInPixelsFromSldUom(const QString &uom, double size)
Returns the size scaled in pixels according to the uom attribute.
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 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 QString encodeScaleMethod(Qgis::ScaleMethod scaleMethod)
Encodes a symbol scale method to a string.
static Qt::PenStyle decodePenStyle(const QString &str)
static void createRotationElement(QDomDocument &doc, QDomElement &element, const QString &rotationFunc)
static QString encodePoint(QPointF point)
Encodes a QPointF to a string.
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
static QPointF decodePoint(const QString &string)
Decodes a QSizeF from a string.
@ PropertyStrokeStyle
Stroke style (eg solid, dashed)
@ PropertyCapStyle
Line cap style.
@ PropertyAngle
Symbol angle.
@ PropertySize
Symbol size.
@ PropertyJoinStyle
Line join style.
@ PropertyOpacity
Opacity.
@ PropertyCharacter
Character, eg for font marker symbol layers.
@ PropertyOffset
Symbol offset.
@ PropertyStrokeWidth
Stroke width.
@ PropertyFillColor
Fill color.
@ PropertyFontStyle
Font style.
@ PropertyHeight
Symbol height.
@ PropertyFontFamily
Font family.
@ PropertyName
Name, eg shape name for simple markers.
@ PropertyStrokeColor
Stroke color.
@ PropertyWidth
Symbol width.
static const bool SELECTION_IS_OPAQUE
Whether styles for selected features ignore symbol alpha.
virtual QColor color() const
The fill color.
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.
void restoreOldDataDefinedProperties(const QVariantMap &stringMap)
Restores older data defined properties from string map.
virtual void prepareExpressions(const QgsSymbolRenderContext &context)
Prepares all data defined property expressions for evaluation.
virtual void setColor(const QColor &color)
The fill color.
void copyPaintEffect(QgsSymbolLayer *destLayer) const
Copies paint effect of this layer to another symbol layer.
QgsPropertyCollection mDataDefinedProperties
virtual bool hasDataDefinedProperties() const
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
QgsFields fields() const
Fields of the layer.
bool selected() const
Returns true if symbols should be rendered using the selected symbol coloring and style.
Qgis::SymbolRenderHints renderHints() const
Returns the rendering hint flags for the symbol.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
const QgsFeature * feature() const
Returns the current feature being rendered.
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for data defined symbology.
qreal opacity() const
Returns the opacity for the symbol.
Abstract base class for all rendered symbols.
Qgis::SymbolType type() const
Returns the symbol's type.
static Q_INVOKABLE QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
static Q_INVOKABLE QgsUnitTypes::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
RenderUnit
Rendering size units.
@ RenderUnknownUnit
Mixed or unknown units.
@ RenderMetersInMapUnits
Meters value as Map units.
@ RenderPercentage
Percentage of another measurement (e.g., canvas size, feature size)
@ RenderMillimeters
Millimeters.
@ RenderMapUnits
Map units.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
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
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
QVector< QgsPointSequence > QgsRingSequence
QVector< QgsPoint > QgsPointSequence
#define QgsDebugMsgLevel(str, level)
Q_GUI_EXPORT int qt_defaultDpiX()
Q_GUI_EXPORT int qt_defaultDpiY()
#define DEFAULT_FONTMARKER_JOINSTYLE
#define DEFAULT_RASTERMARKER_ANGLE
#define DEFAULT_RASTERMARKER_SIZE
#define DEFAULT_SVGMARKER_ANGLE
#define DEFAULT_SIMPLEMARKER_JOINSTYLE
#define DEFAULT_FONTMARKER_CHR
#define DEFAULT_SIMPLEMARKER_BORDERCOLOR
#define DEFAULT_SIMPLEMARKER_SIZE
#define DEFAULT_SIMPLEMARKER_NAME
#define DEFAULT_SIMPLEMARKER_ANGLE
#define DEFAULT_SVGMARKER_SIZE
#define DEFAULT_FONTMARKER_FONT
#define DEFAULT_FONTMARKER_BORDERCOLOR
#define DEFAULT_FONTMARKER_ANGLE
#define DEFAULT_FONTMARKER_COLOR
#define DEFAULT_FONTMARKER_SIZE
#define DEFAULT_SIMPLEMARKER_COLOR
#define DEFAULT_SCALE_METHOD