53#include <QDomDocument>
63#include <QRegularExpression>
66#define POINTS_TO_MM 2.83464567
70 return QStringLiteral(
"%1,%2,%3,%4" ).arg( color.red() ).arg( color.green() ).arg( color.blue() ).arg( color.alpha() );
75 const QStringList lst = str.split(
',' );
76 if ( lst.count() < 3 )
80 int red, green, blue, alpha;
82 green = lst[1].toInt();
83 blue = lst[2].toInt();
85 if ( lst.count() > 3 )
87 alpha = lst[3].toInt();
89 return QColor( red, green, blue, alpha );
94 return QString::number( alpha / 255.0,
'g', 2 );
100 double alpha = str.toDouble( &ok );
101 if ( !ok || alpha > 1 )
103 else if ( alpha < 0 )
112 case QFont::StyleNormal:
113 return QStringLiteral(
"normal" );
114 case QFont::StyleItalic:
115 return QStringLiteral(
"italic" );
116 case QFont::StyleOblique:
117 return QStringLiteral(
"oblique" );
125 if ( str == QLatin1String(
"normal" ) )
return QFont::StyleNormal;
126 if ( str == QLatin1String(
"italic" ) )
return QFont::StyleItalic;
127 if ( str == QLatin1String(
"oblique" ) )
return QFont::StyleOblique;
128 return QFont::StyleNormal;
133 if ( weight == 50 )
return QStringLiteral(
"normal" );
134 if ( weight == 75 )
return QStringLiteral(
"bold" );
138 if ( weight < 0 )
return QStringLiteral(
"100" );
139 if ( weight > 99 )
return QStringLiteral(
"900" );
140 return QString::number( weight * 800 / 99 + 100 );
146 const int weight = str.toInt( &ok );
148 return static_cast< int >( QFont::Normal );
152 if ( weight > 900 )
return 99;
153 if ( weight < 100 )
return 0;
154 return ( weight - 100 ) * 99 / 800;
162 return QStringLiteral(
"no" );
164 return QStringLiteral(
"solid" );
166 return QStringLiteral(
"dash" );
168 return QStringLiteral(
"dot" );
169 case Qt::DashDotLine:
170 return QStringLiteral(
"dash dot" );
171 case Qt::DashDotDotLine:
172 return QStringLiteral(
"dash dot dot" );
174 return QStringLiteral(
"???" );
180 if ( str == QLatin1String(
"no" ) )
return Qt::NoPen;
181 if ( str == QLatin1String(
"solid" ) )
return Qt::SolidLine;
182 if ( str == QLatin1String(
"dash" ) )
return Qt::DashLine;
183 if ( str == QLatin1String(
"dot" ) )
return Qt::DotLine;
184 if ( str == QLatin1String(
"dash dot" ) )
return Qt::DashDotLine;
185 if ( str == QLatin1String(
"dash dot dot" ) )
return Qt::DashDotDotLine;
186 return Qt::SolidLine;
194 return QStringLiteral(
"bevel" );
196 return QStringLiteral(
"miter" );
198 return QStringLiteral(
"round" );
200 return QStringLiteral(
"???" );
206 const QString cleaned = str.toLower().trimmed();
207 if ( cleaned == QLatin1String(
"bevel" ) )
208 return Qt::BevelJoin;
209 if ( cleaned == QLatin1String(
"miter" ) )
210 return Qt::MiterJoin;
211 if ( cleaned == QLatin1String(
"round" ) )
212 return Qt::RoundJoin;
213 return Qt::BevelJoin;
221 return QStringLiteral(
"bevel" );
223 return QStringLiteral(
"mitre" );
225 return QStringLiteral(
"round" );
233 if ( str == QLatin1String(
"bevel" ) )
return Qt::BevelJoin;
234 if ( str == QLatin1String(
"mitre" ) )
return Qt::MiterJoin;
235 if ( str == QLatin1String(
"round" ) )
return Qt::RoundJoin;
236 return Qt::BevelJoin;
244 return QStringLiteral(
"square" );
246 return QStringLiteral(
"flat" );
248 return QStringLiteral(
"round" );
250 return QStringLiteral(
"???" );
256 if ( str == QLatin1String(
"square" ) )
return Qt::SquareCap;
257 if ( str == QLatin1String(
"flat" ) )
return Qt::FlatCap;
258 if ( str == QLatin1String(
"round" ) )
return Qt::RoundCap;
259 return Qt::SquareCap;
267 return QStringLiteral(
"square" );
269 return QStringLiteral(
"butt" );
271 return QStringLiteral(
"round" );
279 if ( str == QLatin1String(
"square" ) )
return Qt::SquareCap;
280 if ( str == QLatin1String(
"butt" ) )
return Qt::FlatCap;
281 if ( str == QLatin1String(
"round" ) )
return Qt::RoundCap;
282 return Qt::SquareCap;
289 case Qt::SolidPattern :
290 return QStringLiteral(
"solid" );
291 case Qt::HorPattern :
292 return QStringLiteral(
"horizontal" );
293 case Qt::VerPattern :
294 return QStringLiteral(
"vertical" );
295 case Qt::CrossPattern :
296 return QStringLiteral(
"cross" );
297 case Qt::BDiagPattern :
298 return QStringLiteral(
"b_diagonal" );
299 case Qt::FDiagPattern :
300 return QStringLiteral(
"f_diagonal" );
301 case Qt::DiagCrossPattern :
302 return QStringLiteral(
"diagonal_x" );
303 case Qt::Dense1Pattern :
304 return QStringLiteral(
"dense1" );
305 case Qt::Dense2Pattern :
306 return QStringLiteral(
"dense2" );
307 case Qt::Dense3Pattern :
308 return QStringLiteral(
"dense3" );
309 case Qt::Dense4Pattern :
310 return QStringLiteral(
"dense4" );
311 case Qt::Dense5Pattern :
312 return QStringLiteral(
"dense5" );
313 case Qt::Dense6Pattern :
314 return QStringLiteral(
"dense6" );
315 case Qt::Dense7Pattern :
316 return QStringLiteral(
"dense7" );
318 return QStringLiteral(
"no" );
320 return QStringLiteral(
"???" );
326 if ( str == QLatin1String(
"solid" ) )
return Qt::SolidPattern;
327 if ( str == QLatin1String(
"horizontal" ) )
return Qt::HorPattern;
328 if ( str == QLatin1String(
"vertical" ) )
return Qt::VerPattern;
329 if ( str == QLatin1String(
"cross" ) )
return Qt::CrossPattern;
330 if ( str == QLatin1String(
"b_diagonal" ) )
return Qt::BDiagPattern;
331 if ( str == QLatin1String(
"f_diagonal" ) )
return Qt::FDiagPattern;
332 if ( str == QLatin1String(
"diagonal_x" ) )
return Qt::DiagCrossPattern;
333 if ( str == QLatin1String(
"dense1" ) )
return Qt::Dense1Pattern;
334 if ( str == QLatin1String(
"dense2" ) )
return Qt::Dense2Pattern;
335 if ( str == QLatin1String(
"dense3" ) )
return Qt::Dense3Pattern;
336 if ( str == QLatin1String(
"dense4" ) )
return Qt::Dense4Pattern;
337 if ( str == QLatin1String(
"dense5" ) )
return Qt::Dense5Pattern;
338 if ( str == QLatin1String(
"dense6" ) )
return Qt::Dense6Pattern;
339 if ( str == QLatin1String(
"dense7" ) )
return Qt::Dense7Pattern;
340 if ( str == QLatin1String(
"no" ) )
return Qt::NoBrush;
341 return Qt::SolidPattern;
348 case Qt::CrossPattern:
349 return QStringLiteral(
"cross" );
350 case Qt::DiagCrossPattern:
351 return QStringLiteral(
"x" );
358 return QStringLiteral(
"horline" );
360 return QStringLiteral(
"line" );
361 case Qt::BDiagPattern:
362 return QStringLiteral(
"slash" );
363 case Qt::FDiagPattern:
364 return QStringLiteral(
"backslash" );
367 case Qt::Dense1Pattern:
368 case Qt::Dense2Pattern:
369 case Qt::Dense3Pattern:
370 case Qt::Dense4Pattern:
371 case Qt::Dense5Pattern:
372 case Qt::Dense6Pattern:
373 case Qt::Dense7Pattern:
383 if ( str == QLatin1String(
"horline" ) )
return Qt::HorPattern;
384 if ( str == QLatin1String(
"line" ) )
return Qt::VerPattern;
385 if ( str == QLatin1String(
"cross" ) )
return Qt::CrossPattern;
386 if ( str == QLatin1String(
"slash" ) )
return Qt::BDiagPattern;
387 if ( str == QLatin1String(
"backshash" ) )
return Qt::FDiagPattern;
388 if ( str == QLatin1String(
"x" ) )
return Qt::DiagCrossPattern;
390 if ( str.startsWith( QLatin1String(
"brush://" ) ) )
406 case Qt::MPenCapStyle:
419 case Qt::SvgMiterJoin:
425 case Qt::MPenJoinStyle:
434 const QDomNodeList children = element.childNodes();
435 for (
int i = 0; i < children.size(); ++i )
437 const QDomElement childElement = children.at( i ).toElement();
438 if ( childElement.tagName() == QLatin1String(
"se:LineSymbolizer" )
439 || childElement.tagName() == QLatin1String(
"se:PointSymbolizer" )
440 || childElement.tagName() == QLatin1String(
"se:PolygonSymbolizer" ) )
448 const QString compareString =
string.trimmed();
452 if ( compareString.compare( QLatin1String(
"feature" ), Qt::CaseInsensitive ) == 0 )
454 else if ( compareString.compare( QLatin1String(
"viewport" ), Qt::CaseInsensitive ) == 0 )
464 switch ( coordinateReference )
467 return QStringLiteral(
"feature" );
469 return QStringLiteral(
"viewport" );
480 const QString s = value.toString().toLower().trimmed();
481 if ( s == QLatin1String(
"single" ) )
483 else if ( s == QLatin1String(
"reversed" ) )
485 else if ( s == QLatin1String(
"double" ) )
487 else if ( value.toInt() == 1 )
489 else if ( value.toInt() == 2 )
491 else if ( value.toInt( &intOk ) == 0 && intOk )
505 const QString s = value.toString().toLower().trimmed();
506 if ( s == QLatin1String(
"plain" ) )
508 else if ( s == QLatin1String(
"lefthalf" ) )
510 else if ( s == QLatin1String(
"righthalf" ) )
512 else if ( value.toInt() == 1 )
514 else if ( value.toInt() == 2 )
516 else if ( value.toInt( &intOk ) == 0 && intOk )
526 const QString compareString =
string.trimmed();
530 if ( compareString.compare( QLatin1String(
"no" ), Qt::CaseInsensitive ) == 0 )
532 else if ( compareString.compare( QLatin1String(
"shape" ), Qt::CaseInsensitive ) == 0 )
534 else if ( compareString.compare( QLatin1String(
"centroid_within" ), Qt::CaseInsensitive ) == 0 )
536 else if ( compareString.compare( QLatin1String(
"completely_within" ), Qt::CaseInsensitive ) == 0 )
549 return QStringLiteral(
"no" );
551 return QStringLiteral(
"shape" );
553 return QStringLiteral(
"centroid_within" );
555 return QStringLiteral(
"completely_within" );
562 const QString compareString =
string.trimmed();
566 if ( compareString.compare( QLatin1String(
"no" ), Qt::CaseInsensitive ) == 0 )
568 else if ( compareString.compare( QLatin1String(
"during_render" ), Qt::CaseInsensitive ) == 0 )
570 else if ( compareString.compare( QLatin1String(
"before_render" ), Qt::CaseInsensitive ) == 0 )
583 return QStringLiteral(
"no" );
585 return QStringLiteral(
"during_render" );
587 return QStringLiteral(
"before_render" );
599 QStringList lst = str.split(
',' );
600 if ( lst.count() != 2 )
601 return QPointF( 0, 0 );
602 return QPointF( lst[0].toDouble(), lst[1].toDouble() );
613 if ( value.userType() == QMetaType::Type::QVariantList )
615 const QVariantList list = value.toList();
616 if ( list.size() != 2 )
620 bool convertOk =
false;
621 const double x = list.at( 0 ).toDouble( &convertOk );
624 const double y = list.at( 1 ).toDouble( &convertOk );
629 return QPointF( x, y );
637 const QStringList list = value.toString().trimmed().split(
',' );
638 if ( list.count() != 2 )
640 bool convertOk =
false;
641 const double x = list.at( 0 ).toDouble( &convertOk );
644 const double y = list.at( 1 ).toDouble( &convertOk );
649 return QPointF( x, y );
663 QStringList lst =
string.split(
',' );
664 if ( lst.count() != 2 )
665 return QSizeF( 0, 0 );
666 return QSizeF( lst[0].toDouble(), lst[1].toDouble() );
677 if ( value.userType() == QMetaType::Type::QVariantList )
679 const QVariantList list = value.toList();
680 if ( list.size() != 2 )
684 bool convertOk =
false;
685 const double x = list.at( 0 ).toDouble( &convertOk );
688 const double y = list.at( 1 ).toDouble( &convertOk );
693 return QSizeF( x, y );
701 const QStringList list = value.toString().trimmed().split(
',' );
702 if ( list.count() != 2 )
704 bool convertOk =
false;
705 const double x = list.at( 0 ).toDouble( &convertOk );
708 const double y = list.at( 1 ).toDouble( &convertOk );
713 return QSizeF( x, y );
734 if ( str.startsWith( QLatin1String(
"3x:" ) ) )
737 const QString chopped = str.mid( 3 );
738 lst = chopped.split(
',' );
742 lst = str.split(
',' );
744 if ( lst.count() < 2 )
747 double minScale = lst[0].toDouble();
749 minScale = minScale != 0 ? 1.0 / minScale : 0;
750 double maxScale = lst[1].toDouble();
752 maxScale = maxScale != 0 ? 1.0 / maxScale : 0;
754 if ( lst.count() < 6 )
774 *scaleFactor = 0.001;
775 return QStringLiteral(
"http://www.opengeospatial.org/se/units/metre" );
780 return QStringLiteral(
"http://www.opengeospatial.org/se/units/metre" );
787 *scaleFactor = 1 / 0.28;
796 if ( str == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
802 else if ( str == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
805 *scaleFactor = 0.3048;
820 QString vectorString;
821 QVector<qreal>::const_iterator it = v.constBegin();
822 for ( ; it != v.constEnd(); ++it )
824 if ( it != v.constBegin() )
826 vectorString.append(
';' );
828 vectorString.append( QString::number( *it ) );
835 QVector<qreal> resultVector;
837 const QStringList realList = s.split(
';' );
838 QStringList::const_iterator it = realList.constBegin();
839 for ( ; it != realList.constEnd(); ++it )
841 resultVector.append( it->toDouble() );
849 QString vectorString;
850 QVector<qreal>::const_iterator it = v.constBegin();
851 for ( ; it != v.constEnd(); ++it )
853 if ( it != v.constBegin() )
855 vectorString.append(
' ' );
857 vectorString.append( QString::number( *it ) );
864 QVector<qreal> resultVector;
866 const QStringList realList = s.split(
' ' );
867 QStringList::const_iterator it = realList.constBegin();
868 for ( ; it != realList.constEnd(); ++it )
870 resultVector.append( it->toDouble() );
878 QString encodedValue;
880 switch ( scaleMethod )
883 encodedValue = QStringLiteral(
"diameter" );
886 encodedValue = QStringLiteral(
"area" );
896 if ( str == QLatin1String(
"diameter" ) )
910 if ( s.compare( QLatin1String(
"Lighten" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Lighten;
911 if ( s.compare( QLatin1String(
"Screen" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Screen;
912 if ( s.compare( QLatin1String(
"Dodge" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorDodge;
913 if ( s.compare( QLatin1String(
"Addition" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Plus;
914 if ( s.compare( QLatin1String(
"Darken" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Darken;
915 if ( s.compare( QLatin1String(
"Multiply" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Multiply;
916 if ( s.compare( QLatin1String(
"Burn" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorBurn;
917 if ( s.compare( QLatin1String(
"Overlay" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Overlay;
918 if ( s.compare( QLatin1String(
"SoftLight" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_SoftLight;
919 if ( s.compare( QLatin1String(
"HardLight" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_HardLight;
920 if ( s.compare( QLatin1String(
"Difference" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Difference;
921 if ( s.compare( QLatin1String(
"Subtract" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Exclusion;
922 return QPainter::CompositionMode_SourceOver;
927 return QIcon(
symbolPreviewPixmap( symbol, size, padding,
nullptr,
false,
nullptr, shape, screen ) );
935 QPixmap pixmap( size * devicePixelRatio );
936 pixmap.setDevicePixelRatio( devicePixelRatio );
938 pixmap.fill( Qt::transparent );
940 painter.begin( &pixmap );
945 painter.setRenderHint( QPainter::Antialiasing );
946 painter.setRenderHint( QPainter::SmoothPixmapTransform );
956 size.setWidth( size.rwidth() - ( padding * 2 ) );
957 size.setHeight( size.rheight() - ( padding * 2 ) );
958 painter.translate( padding, padding );
968 std::unique_ptr<QgsSymbol> symbol_noDD( symbol->
clone( ) );
970 for (
const auto &layer : layers )
972 for (
int i = 0; i < layer->dataDefinedProperties().count(); ++i )
974 QgsProperty &prop = layer->dataDefinedProperties().property( i );
980 symbol_noDD->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape, screen );
984 std::unique_ptr<QgsSymbol> symbolClone( symbol->
clone( ) );
985 symbolClone->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape, screen );
999 maxBleed = layerMaxBleed > maxBleed ? layerMaxBleed : maxBleed;
1009 painter.begin( &picture );
1010 painter.setRenderHint( QPainter::Antialiasing );
1020 switch ( parentSymbolType )
1035 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
1036 layerClone->drawPreviewIcon( symbolContext, size );
1044 QPixmap pixmap( size * devicePixelRatio );
1045 pixmap.setDevicePixelRatio( devicePixelRatio );
1046 pixmap.fill( Qt::transparent );
1048 painter.begin( &pixmap );
1049 painter.setRenderHint( QPainter::Antialiasing );
1067 switch ( parentSymbolType )
1082 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
1083 layerClone->drawPreviewIcon( symbolContext, size );
1085 return QIcon( pixmap );
1095 QPixmap pixmap( size );
1096 pixmap.fill( Qt::transparent );
1099 painter.begin( &pixmap );
1102 if ( drawTransparentBackground )
1103 drawStippledBackground( &painter, QRect( padding, padding, size.width() - padding * 2, size.height() - padding * 2 ) );
1107 switch ( direction )
1109 case Qt::Horizontal:
1111 for (
int i = 0; i < size.width(); i++ )
1113 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.width() ) );
1114 painter.setPen( pen );
1115 const int x = flipDirection ? size.width() - i - 1 : i;
1116 painter.drawLine( x, 0 + padding, x, size.height() - 1 - padding );
1123 for (
int i = 0; i < size.height(); i++ )
1125 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.height() ) );
1126 painter.setPen( pen );
1127 const int y = flipDirection ? size.height() - i - 1 : i;
1128 painter.drawLine( 0 + padding, y, size.width() - 1 - padding, y );
1141 uchar pixDataRGB[] = { 255, 255, 255, 255,
1146 const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
1148 const int width = ( rect.width() < rect.height() ) ?
1149 rect.width() / 2.5 : rect.height() / 2.5;
1150 const QPixmap pix = QPixmap::fromImage( img.scaled( width, width ) );
1153 brush.setTexture( pix );
1154 painter->fillRect( rect, brush );
1159 const qreal s = ( markerSize - 1 ) / 2.0;
1164 p.setPen( QColor( 50, 100, 120, 200 ) );
1165 p.setBrush( QColor( 200, 200, 210, 120 ) );
1166 p.drawEllipse( x - s, y - s, s * 2, s * 2 );
1169 p.setPen( QColor( 255, 0, 0 ) );
1170 p.drawLine( x - s, y + s, x + s, y - s );
1171 p.drawLine( x - s, y - s, x + s, y + s );
1183static QPolygonF makeOffsetGeometry(
const QgsPolylineXY &polyline )
1185 int i, pointCount = polyline.count();
1187 QPolygonF resultLine;
1188 resultLine.resize( pointCount );
1192 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1193 resultLine[i] = QPointF( tempPtr->
x(), tempPtr->
y() );
1197static QList<QPolygonF> makeOffsetGeometry(
const QgsPolygonXY &polygon )
1199 QList<QPolygonF> resultGeom;
1200 resultGeom.reserve( polygon.size() );
1201 for (
int ring = 0; ring < polygon.size(); ++ring )
1202 resultGeom.append( makeOffsetGeometry( polygon[ ring ] ) );
1208 QList<QPolygonF> resultLine;
1210 if ( polyline.count() < 2 )
1212 resultLine.append( polyline );
1216 unsigned int i, pointCount = polyline.count();
1219 QPointF *tempPtr = polyline.data();
1220 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1221 tempPolyline[i] =
QgsPointXY( tempPtr->rx(), tempPtr->ry() );
1224 if ( !tempGeometry.
isNull() )
1226 const int quadSegments = 0;
1227 const double miterLimit = 2.0;
1235 if ( !offsetGeom.
isNull() )
1237 tempGeometry = offsetGeom;
1242 resultLine.append( makeOffsetGeometry( line ) );
1247 resultLine.append( makeOffsetGeometry( tempGeometry.
asPolygon() ) );
1253 resultLine.reserve( tempMPolyline.count() );
1254 for (
int part = 0; part < tempMPolyline.count(); ++part )
1256 resultLine.append( makeOffsetGeometry( tempMPolyline[ part ] ) );
1263 resultLine.reserve( tempMPolygon.count() );
1264 for (
int part = 0; part < tempMPolygon.count(); ++part )
1266 resultLine.append( makeOffsetGeometry( tempMPolygon[ part ] ) );
1274 resultLine.append( polyline );
1283 if ( element.isNull() )
1287 QDomNode layerNode = element.firstChild();
1289 while ( !layerNode.isNull() )
1291 QDomElement e = layerNode.toElement();
1292 if ( !e.isNull() && e.tagName() != QLatin1String(
"data_defined_properties" ) && e.tagName() != QLatin1String(
"buffer" ) )
1294 if ( e.tagName() != QLatin1String(
"layer" ) )
1300 std::unique_ptr< QgsSymbolLayer > layer =
loadSymbolLayer( e, context );
1304 const QDomElement s = e.firstChildElement( QStringLiteral(
"symbol" ) );
1307 std::unique_ptr< QgsSymbol > subSymbol(
loadSymbol( s, context ) );
1314 layers.append( layer.release() );
1316 for (
int i = 0; i < subSymbol->symbolLayerCount(); ++i )
1318 layers.append( subSymbol->symbolLayer( i )->clone() );
1323 const bool res = layer->setSubSymbol( subSymbol.release() );
1326 QgsDebugError( QStringLiteral(
"symbol layer refused subsymbol: " ) + s.attribute(
"name" ) );
1328 layers.append( layer.release() );
1333 layers.append( layer.release() );
1338 layerNode = layerNode.nextSibling();
1341 if ( layers.isEmpty() )
1347 const QString symbolType = element.attribute( QStringLiteral(
"type" ) );
1349 std::unique_ptr< QgsSymbol > symbol;
1350 if ( symbolType == QLatin1String(
"line" ) )
1351 symbol = std::make_unique< QgsLineSymbol >( layers );
1352 else if ( symbolType == QLatin1String(
"fill" ) )
1353 symbol = std::make_unique< QgsFillSymbol >( layers );
1354 else if ( symbolType == QLatin1String(
"marker" ) )
1355 symbol = std::make_unique< QgsMarkerSymbol >( layers );
1362 if ( element.hasAttribute( QStringLiteral(
"outputUnit" ) ) )
1366 if ( element.hasAttribute( ( QStringLiteral(
"mapUnitScale" ) ) ) )
1369 const double oldMin = element.attribute( QStringLiteral(
"mapUnitMinScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1370 mapUnitScale.
minScale = oldMin != 0 ? 1.0 / oldMin : 0;
1371 const double oldMax = element.attribute( QStringLiteral(
"mapUnitMaxScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1372 mapUnitScale.
maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
1373 symbol->setMapUnitScale( mapUnitScale );
1375 symbol->setOpacity( element.attribute( QStringLiteral(
"alpha" ), QStringLiteral(
"1.0" ) ).toDouble() );
1376 symbol->setExtentBuffer( element.attribute( QStringLiteral(
"extent_buffer" ), QStringLiteral(
"0.0" ) ).toDouble() );
1377 symbol->setExtentBufferSizeUnit(
QgsUnitTypes::decodeRenderUnit( element.attribute( QStringLiteral(
"extent_buffer_unit" ), QStringLiteral(
"MapUnit" ) ) ) );
1378 symbol->setClipFeaturesToExtent( element.attribute( QStringLiteral(
"clip_to_extent" ), QStringLiteral(
"1" ) ).toInt() );
1379 symbol->setForceRHR( element.attribute( QStringLiteral(
"force_rhr" ), QStringLiteral(
"0" ) ).toInt() );
1381 if ( element.attribute( QStringLiteral(
"renderer_should_use_levels" ), QStringLiteral(
"0" ) ).toInt() )
1383 symbol->setFlags( flags );
1385 symbol->animationSettings().setIsAnimated( element.attribute( QStringLiteral(
"is_animated" ), QStringLiteral(
"0" ) ).toInt() );
1386 symbol->animationSettings().setFrameRate( element.attribute( QStringLiteral(
"frame_rate" ), QStringLiteral(
"10" ) ).toDouble() );
1388 if ( !element.firstChildElement( QStringLiteral(
"buffer" ) ).isNull() )
1390 auto bufferSettings = std::make_unique< QgsSymbolBufferSettings >();
1391 bufferSettings->readXml( element, context );
1392 symbol->setBufferSettings( bufferSettings.release() );
1396 symbol->setBufferSettings(
nullptr );
1399 const QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1400 if ( !ddProps.isNull() )
1410 const QString layerClass = element.attribute( QStringLiteral(
"class" ) );
1411 const bool locked = element.attribute( QStringLiteral(
"locked" ) ).toInt();
1412 const bool enabled = element.attribute( QStringLiteral(
"enabled" ), QStringLiteral(
"1" ) ).toInt();
1413 const int pass = element.attribute( QStringLiteral(
"pass" ) ).toInt();
1414 const QString
id = element.attribute( QStringLiteral(
"id" ) );
1428 layer->setLocked( locked );
1429 layer->setRenderingPass( pass );
1430 layer->setEnabled( enabled );
1431 layer->setUserFlags( userFlags );
1434 if ( !
id.isEmpty() )
1438 const QDomElement effectElem = element.firstChildElement( QStringLiteral(
"effect" ) );
1439 if ( !effectElem.isNull() )
1443 layer->setPaintEffect( effect.release() );
1447 const QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1448 if ( !ddProps.isNull() )
1455 const QSet< int > oldKeys = prevProperties.
propertyKeys();
1456 for (
int key : oldKeys )
1458 if ( !layer->dataDefinedProperties().propertyKeys().contains( key ) )
1477 return QStringLiteral(
"line" );
1479 return QStringLiteral(
"marker" );
1481 return QStringLiteral(
"fill" );
1490 QDomElement symEl = doc.createElement( QStringLiteral(
"symbol" ) );
1491 symEl.setAttribute( QStringLiteral(
"type" ), _nameForSymbolType( symbol->
type() ) );
1492 symEl.setAttribute( QStringLiteral(
"name" ), name );
1493 symEl.setAttribute( QStringLiteral(
"alpha" ), QString::number( symbol->
opacity() ) );
1494 symEl.setAttribute( QStringLiteral(
"clip_to_extent" ), symbol->
clipFeaturesToExtent() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1497 symEl.setAttribute( QStringLiteral(
"extent_buffer" ), QString::number( symbol->
extentBuffer() ) );
1500 symEl.setAttribute( QStringLiteral(
"force_rhr" ), symbol->
forceRHR() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1502 symEl.setAttribute( QStringLiteral(
"renderer_should_use_levels" ), QStringLiteral(
"1" ) );
1504 symEl.setAttribute( QStringLiteral(
"is_animated" ), symbol->
animationSettings().
isAnimated() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1508 bufferSettings->writeXml( symEl, context );
1512 QDomElement ddProps = doc.createElement( QStringLiteral(
"data_defined_properties" ) );
1514 symEl.appendChild( ddProps );
1520 QDomElement layerEl = doc.createElement( QStringLiteral(
"layer" ) );
1521 layerEl.setAttribute( QStringLiteral(
"class" ), layer->
layerType() );
1522 layerEl.setAttribute( QStringLiteral(
"enabled" ), layer->
enabled() );
1523 layerEl.setAttribute( QStringLiteral(
"locked" ), layer->
isLocked() );
1524 layerEl.setAttribute( QStringLiteral(
"pass" ), layer->
renderingPass() );
1525 layerEl.setAttribute( QStringLiteral(
"id" ), layer->
id() );
1539 QDomElement ddProps = doc.createElement( QStringLiteral(
"data_defined_properties" ) );
1541 layerEl.appendChild( ddProps );
1545 const QString subname = QStringLiteral(
"@%1@%2" ).arg( name ).arg( i );
1546 const QDomElement subEl =
saveSymbol( subname, subSymbol, doc, context );
1547 layerEl.appendChild( subEl );
1549 symEl.appendChild( layerEl );
1557 QDomDocument doc( QStringLiteral(
"qgis-symbol-definition" ) );
1560 QTextStream stream( &props );
1561 symbolElem.save( stream, -1 );
1567 QList<QgsSymbolLayer *> &layers )
1571 if ( element.isNull() )
1574 const QString symbolizerName = element.localName();
1576 if ( symbolizerName == QLatin1String(
"PointSymbolizer" ) )
1579 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1580 if ( graphicElem.isNull() )
1582 QgsDebugError( QStringLiteral(
"Graphic element not found in PointSymbolizer" ) );
1593 layers.append( l.release() );
1603 layers.append( l.release() );
1613 layers.append( l.release() );
1625 if ( symbolizerName == QLatin1String(
"LineSymbolizer" ) )
1628 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1629 if ( strokeElem.isNull() )
1631 QgsDebugError( QStringLiteral(
"Stroke element not found in LineSymbolizer" ) );
1644 layers.append( l.release() );
1654 layers.append( l.release() );
1666 if ( symbolizerName == QLatin1String(
"PolygonSymbolizer" ) )
1669 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1670 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1671 if ( fillElem.isNull() && strokeElem.isNull() )
1673 QgsDebugError( QStringLiteral(
"neither Fill nor Stroke element not found in PolygonSymbolizer" ) );
1687 layers.append( l.release() );
1691 if ( lastLayer->
layerType() == QLatin1String(
"SimpleFill" ) || lastLayer->
layerType() == QLatin1String(
"SVGFill" ) )
1699 layers.append( l.release() );
1709 layers.append( l.release() );
1732 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1733 if ( fillElem.isNull() )
1735 QgsDebugError( QStringLiteral(
"Fill element not found" ) );
1739 std::unique_ptr< QgsSymbolLayer > l;
1757 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1758 if ( strokeElem.isNull() )
1760 QgsDebugError( QStringLiteral(
"Stroke element not found" ) );
1764 std::unique_ptr< QgsSymbolLayer > l;
1776 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1777 if ( graphicElem.isNull() )
1779 QgsDebugError( QStringLiteral(
"Graphic element not found" ) );
1783 std::unique_ptr< QgsSymbolLayer > l;
1806 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1807 if ( graphicElem.isNull() )
1810 const QDomElement externalGraphicElem = graphicElem.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
1811 if ( externalGraphicElem.isNull() )
1815 const QDomElement formatElem = externalGraphicElem.firstChildElement( QStringLiteral(
"Format" ) );
1816 if ( formatElem.isNull() )
1819 const QString elementFormat = formatElem.firstChild().nodeValue();
1820 if ( ! format.isEmpty() && elementFormat != format )
1822 QgsDebugMsgLevel(
"unsupported External Graphic format found: " + elementFormat, 4 );
1827 const QDomElement onlineResourceElem = externalGraphicElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1828 const QDomElement inlineContentElem = externalGraphicElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1830 if ( !onlineResourceElem.isNull() )
1834 else if ( !inlineContentElem.isNull() )
1847 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1848 if ( graphicElem.isNull() )
1851 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1852 if ( markElem.isNull() )
1855 const QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
1856 return !wellKnownNameElem.isNull();
1862 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1863 if ( graphicElem.isNull() )
1866 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1867 if ( markElem.isNull() )
1871 const QDomElement formatElem = markElem.firstChildElement( QStringLiteral(
"Format" ) );
1872 if ( formatElem.isNull() )
1875 const QString format = formatElem.firstChild().nodeValue();
1876 if ( format != QLatin1String(
"ttf" ) )
1878 QgsDebugError(
"unsupported Graphic Mark format found: " + format );
1883 const QDomElement onlineResourceElem = markElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1884 const QDomElement inlineContentElem = markElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1885 if ( !onlineResourceElem.isNull() )
1888 const QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
1889 if ( !markIndexElem.isNull() )
1892 else if ( !inlineContentElem.isNull() )
1913 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1914 if ( graphicElem.isNull() )
1918 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
1920 if ( it.key() == QLatin1String(
"widthHeightFactor" ) )
1931 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1932 if ( strokeElem.isNull() )
1935 QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral(
"GraphicStroke" ) );
1936 if ( graphicStrokeElem.isNull() )
1944 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1945 if ( fillElem.isNull() )
1948 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1949 if ( graphicFillElem.isNull() )
1952 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1953 if ( graphicElem.isNull() )
1959 QColor fillColor, strokeColor;
1960 double size, strokeWidth;
1961 Qt::PenStyle strokeStyle;
1962 if ( !
wellKnownMarkerFromSld( graphicElem, name, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
1965 if ( name != QLatin1String(
"horline" ) )
1973 const double angle = angleFunc.toDouble( &ok );
1979 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1980 if ( fillElem.isNull() )
1983 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1984 if ( graphicFillElem.isNull() )
1987 const QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1988 if ( graphicElem.isNull() )
1991 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1992 if ( markElem.isNull() )
2000 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
2001 if ( fillElem.isNull() )
2004 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
2005 if ( graphicFillElem.isNull() )
2013 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
2014 if ( fillElem.isNull() )
2017 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
2018 if ( graphicFillElem.isNull() )
2038 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
2039 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
2043 bool validFill =
false, validStroke =
false;
2048 Qt::BrushStyle fillStyle;
2050 if (
fillFromSld( fillElem, fillStyle, fillColor ) )
2056 Qt::PenStyle strokeStyle;
2057 double strokeWidth = 1.0, dashOffset = 0.0;
2058 QVector<qreal> customDashPattern;
2060 if (
lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth,
2061 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2064 if ( validFill || validStroke )
2067 map[QStringLiteral(
"name" )] = QStringLiteral(
"square" );
2070 map[QStringLiteral(
"size" )] = QString::number( 6 );
2071 map[QStringLiteral(
"angle" )] = QString::number( 0 );
2072 map[QStringLiteral(
"offset" )] =
encodePoint( QPointF( 0, 0 ) );
2079 bool validFill =
false, validStroke =
false;
2082 QString name, format;
2084 QColor fillColor, strokeColor;
2085 double strokeWidth = 1.0, size = 0.0, angle = 0.0;
2089 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
2090 if ( !graphicFillElem.isNull() )
2093 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
2094 if ( !graphicElem.isNull() )
2100 const QDomElement graphicChildElem = graphicElem.firstChildElement();
2101 while ( !graphicChildElem.isNull() )
2103 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2106 const QDomElement wellKnownNameElem = graphicChildElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
2107 if ( !wellKnownNameElem.isNull() )
2109 name = wellKnownNameElem.firstChild().nodeValue();
2115 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) || graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2118 const QDomElement formatElem = graphicChildElem.firstChildElement( QStringLiteral(
"Format" ) );
2119 if ( formatElem.isNull() )
2122 format = formatElem.firstChild().nodeValue();
2126 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) && format != QLatin1String(
"image/svg+xml" ) )
2131 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format != QLatin1String(
"ttf" ) )
2135 const QDomElement onlineResourceElem = graphicChildElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
2136 const QDomElement inlineContentElem = graphicChildElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
2138 if ( !onlineResourceElem.isNull() )
2140 name = onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) );
2142 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format == QLatin1String(
"ttf" ) )
2145 if ( name.startsWith( QLatin1String(
"ttf://" ) ) )
2146 name = name.mid( 6 );
2149 const QDomElement markIndexElem = graphicChildElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
2150 if ( markIndexElem.isNull() )
2154 const int v = markIndexElem.firstChild().nodeValue().toInt( &ok );
2165 else if ( !inlineContentElem.isNull() )
2175 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2177 name = QStringLiteral(
"square" );
2184 if ( found && graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2191 Qt::BrushStyle markFillStyle;
2193 QDomElement markFillElem = graphicChildElem.firstChildElement( QStringLiteral(
"Fill" ) );
2194 if (
fillFromSld( markFillElem, markFillStyle, fillColor ) )
2199 Qt::PenStyle strokeStyle;
2200 double strokeWidth = 1.0, dashOffset = 0.0;
2201 QVector<qreal> customDashPattern;
2203 QDomElement markStrokeElem = graphicChildElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2204 if (
lineFromSld( markStrokeElem, strokeStyle, strokeColor, strokeWidth,
2205 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2212 const QDomElement opacityElem = graphicElem.firstChildElement( QStringLiteral(
"Opacity" ) );
2213 if ( !opacityElem.isNull() )
2214 fillColor.setAlpha(
decodeSldAlpha( opacityElem.firstChild().nodeValue() ) );
2216 const QDomElement sizeElem = graphicElem.firstChildElement( QStringLiteral(
"Size" ) );
2217 if ( !sizeElem.isNull() )
2220 const double v = sizeElem.firstChild().nodeValue().toDouble( &ok );
2229 const double v = angleFunc.toDouble( &ok );
2239 if ( validFill || validStroke )
2241 if ( format == QLatin1String(
"image/svg+xml" ) )
2244 map[QStringLiteral(
"name" )] = name;
2245 map[QStringLiteral(
"fill" )] = fillColor.name();
2246 map[QStringLiteral(
"outline" )] = strokeColor.name();
2247 map[QStringLiteral(
"outline-width" )] = QString::number( strokeWidth );
2249 map[QStringLiteral(
"size" )] = QString::number( size );
2251 map[QStringLiteral(
"angle" )] = QString::number( angle );
2252 if ( !offset.isNull() )
2253 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
2256 else if ( format == QLatin1String(
"ttf" ) )
2259 map[QStringLiteral(
"font" )] = name;
2260 map[QStringLiteral(
"chr" )] = markIndex;
2263 map[QStringLiteral(
"size" )] = QString::number( size );
2265 map[QStringLiteral(
"angle" )] = QString::number( angle );
2266 if ( !offset.isNull() )
2267 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
2273 if ( layers.isEmpty() )
2276 layerList << layers;
2284 fillToSld( doc, element, context, brushStyle, color );
2289 QString patternName;
2290 switch ( brushStyle )
2295 case Qt::SolidPattern:
2296 if ( color.isValid() )
2299 if ( color.alpha() < 255 )
2304 case Qt::CrossPattern:
2305 case Qt::DiagCrossPattern:
2306 case Qt::HorPattern:
2307 case Qt::VerPattern:
2308 case Qt::BDiagPattern:
2309 case Qt::FDiagPattern:
2310 case Qt::Dense1Pattern:
2311 case Qt::Dense2Pattern:
2312 case Qt::Dense3Pattern:
2313 case Qt::Dense4Pattern:
2314 case Qt::Dense5Pattern:
2315 case Qt::Dense6Pattern:
2316 case Qt::Dense7Pattern:
2321 context.
pushWarning( QObject::tr(
"Brush style '%1' is not supported for SLD" ).arg( brushStyle ) );
2325 QDomElement graphicFillElem = doc.createElement( QStringLiteral(
"se:GraphicFill" ) );
2326 element.appendChild( graphicFillElem );
2328 QDomElement graphicElem = doc.createElement( QStringLiteral(
"se:Graphic" ) );
2329 graphicFillElem.appendChild( graphicElem );
2331 const QColor fillColor = patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
2332 const QColor strokeColor = !patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
2335 wellKnownMarkerToSld( doc, graphicElem, patternName, fillColor, strokeColor, Qt::SolidLine, context, -1, -1 );
2342 brushStyle = Qt::SolidPattern;
2343 color = QColor( 128, 128, 128 );
2345 if ( element.isNull() )
2347 brushStyle = Qt::NoBrush;
2352 const QDomElement graphicFillElem = element.firstChildElement( QStringLiteral(
"GraphicFill" ) );
2354 if ( graphicFillElem.isNull() )
2357 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2359 QgsDebugMsgLevel( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ), 2 );
2361 if ( it.key() == QLatin1String(
"fill" ) )
2362 color = QColor( it.value() );
2363 else if ( it.key() == QLatin1String(
"fill-opacity" ) )
2369 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
2370 if ( graphicElem.isNull() )
2373 QString patternName = QStringLiteral(
"square" );
2374 QColor fillColor, strokeColor;
2375 double strokeWidth, size;
2376 Qt::PenStyle strokeStyle;
2377 if ( !
wellKnownMarkerFromSld( graphicElem, patternName, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
2381 if ( brushStyle == Qt::NoBrush )
2384 const QColor
c = patternName.startsWith( QLatin1String(
"brush://" ) ) ? fillColor : strokeColor;
2394 const Qt::PenJoinStyle *penJoinStyle,
const Qt::PenCapStyle *penCapStyle,
2395 const QVector<qreal> *customDashPattern,
double dashOffset )
2397 QVector<qreal> dashPattern;
2398 const QVector<qreal> *pattern = &dashPattern;
2400 if ( penStyle == Qt::CustomDashLine && !customDashPattern )
2402 context.
pushWarning( QObject::tr(
"WARNING: Custom dash pattern required but not provided. Using default dash pattern." ) );
2403 penStyle = Qt::DashLine;
2415 dashPattern.push_back( 4.0 );
2416 dashPattern.push_back( 2.0 );
2419 dashPattern.push_back( 1.0 );
2420 dashPattern.push_back( 2.0 );
2422 case Qt::DashDotLine:
2423 dashPattern.push_back( 4.0 );
2424 dashPattern.push_back( 2.0 );
2425 dashPattern.push_back( 1.0 );
2426 dashPattern.push_back( 2.0 );
2428 case Qt::DashDotDotLine:
2429 dashPattern.push_back( 4.0 );
2430 dashPattern.push_back( 2.0 );
2431 dashPattern.push_back( 1.0 );
2432 dashPattern.push_back( 2.0 );
2433 dashPattern.push_back( 1.0 );
2434 dashPattern.push_back( 2.0 );
2437 case Qt::CustomDashLine:
2438 Q_ASSERT( customDashPattern );
2439 pattern = customDashPattern;
2443 context.
pushWarning( QObject::tr(
"Pen style '%1' is not supported for SLD" ).arg( penStyle ) );
2447 if ( color.isValid() )
2450 if ( color.alpha() < 255 )
2457 else if ( width == 0 )
2467 if ( !pattern->isEmpty() )
2477 Qt::PenStyle &penStyle, QColor &color,
double &width,
2478 Qt::PenJoinStyle *penJoinStyle, Qt::PenCapStyle *penCapStyle,
2479 QVector<qreal> *customDashPattern,
double *dashOffset )
2483 penStyle = Qt::SolidLine;
2484 color = QColor( 0, 0, 0 );
2487 *penJoinStyle = Qt::BevelJoin;
2489 *penCapStyle = Qt::SquareCap;
2490 if ( customDashPattern )
2491 customDashPattern->clear();
2495 if ( element.isNull() )
2497 penStyle = Qt::NoPen;
2503 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2505 QgsDebugMsgLevel( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ), 2 );
2507 if ( it.key() == QLatin1String(
"stroke" ) )
2509 color = QColor( it.value() );
2511 else if ( it.key() == QLatin1String(
"stroke-opacity" ) )
2515 else if ( it.key() == QLatin1String(
"stroke-width" ) )
2518 const double w = it.value().toDouble( &ok );
2522 else if ( it.key() == QLatin1String(
"stroke-linejoin" ) && penJoinStyle )
2526 else if ( it.key() == QLatin1String(
"stroke-linecap" ) && penCapStyle )
2530 else if ( it.key() == QLatin1String(
"stroke-dasharray" ) )
2533 if ( !dashPattern.isEmpty() )
2537 bool dashPatternFound =
false;
2539 if ( dashPattern.count() == 2 )
2541 if ( dashPattern.at( 0 ) == 4.0 &&
2542 dashPattern.at( 1 ) == 2.0 )
2544 penStyle = Qt::DashLine;
2545 dashPatternFound =
true;
2547 else if ( dashPattern.at( 0 ) == 1.0 &&
2548 dashPattern.at( 1 ) == 2.0 )
2550 penStyle = Qt::DotLine;
2551 dashPatternFound =
true;
2554 else if ( dashPattern.count() == 4 )
2556 if ( dashPattern.at( 0 ) == 4.0 &&
2557 dashPattern.at( 1 ) == 2.0 &&
2558 dashPattern.at( 2 ) == 1.0 &&
2559 dashPattern.at( 3 ) == 2.0 )
2561 penStyle = Qt::DashDotLine;
2562 dashPatternFound =
true;
2565 else if ( dashPattern.count() == 6 )
2567 if ( dashPattern.at( 0 ) == 4.0 &&
2568 dashPattern.at( 1 ) == 2.0 &&
2569 dashPattern.at( 2 ) == 1.0 &&
2570 dashPattern.at( 3 ) == 2.0 &&
2571 dashPattern.at( 4 ) == 1.0 &&
2572 dashPattern.at( 5 ) == 2.0 )
2574 penStyle = Qt::DashDotDotLine;
2575 dashPatternFound =
true;
2580 if ( !dashPatternFound )
2582 if ( customDashPattern )
2584 penStyle = Qt::CustomDashLine;
2585 *customDashPattern = dashPattern;
2589 QgsDebugMsgLevel( QStringLiteral(
"custom dash pattern required but not provided. Using default dash pattern." ), 2 );
2590 penStyle = Qt::DashLine;
2595 else if ( it.key() == QLatin1String(
"stroke-dashoffset" ) && dashOffset )
2598 const double d = it.value().toDouble( &ok );
2608 const QString &path,
const QString &mime,
2609 const QColor &color,
double size )
2611 QDomElement externalGraphicElem = doc.createElement( QStringLiteral(
"se:ExternalGraphic" ) );
2612 element.appendChild( externalGraphicElem );
2621 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2623 element.appendChild( sizeElem );
2628 const QString &path,
const QColor &fillColor,
double size,
const QColor &strokeColor,
double strokeWidth )
2631 parametricSvgToSld( doc, graphicElem, path, fillColor, size, strokeColor, strokeWidth, context );
2641 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Parametric SVG" ) ) );
2642 const QString parametricPath =
getSvgParametricPath( path, fillColor, strokeColor, strokeWidth );
2645 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Plain SVG fallback, no parameters" ) ) );
2648 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Well known marker fallback" ) ) );
2654 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2656 graphicElem.appendChild( sizeElem );
2663 if ( fillColor.isValid() )
2665 url.addQueryItem( QStringLiteral(
"fill" ), fillColor.name() );
2666 url.addQueryItem( QStringLiteral(
"fill-opacity" ),
encodeSldAlpha( fillColor.alpha() ) );
2670 url.addQueryItem( QStringLiteral(
"fill" ), QStringLiteral(
"#000000" ) );
2671 url.addQueryItem( QStringLiteral(
"fill-opacity" ), QStringLiteral(
"1" ) );
2673 if ( strokeColor.isValid() )
2675 url.addQueryItem( QStringLiteral(
"outline" ), strokeColor.name() );
2676 url.addQueryItem( QStringLiteral(
"outline-opacity" ),
encodeSldAlpha( strokeColor.alpha() ) );
2680 url.addQueryItem( QStringLiteral(
"outline" ), QStringLiteral(
"#000000" ) );
2681 url.addQueryItem( QStringLiteral(
"outline-opacity" ), QStringLiteral(
"1" ) );
2683 url.addQueryItem( QStringLiteral(
"outline-width" ), QString::number( strokeWidth ) );
2684 const QString params = url.toString( QUrl::FullyEncoded );
2685 if ( params.isEmpty() )
2691 return basePath +
"?" + params;
2696 QString &path, QString &mime,
2697 QColor &color,
double &size )
2702 QDomElement externalGraphicElem = element.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
2703 if ( externalGraphicElem.isNull() )
2708 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2709 if ( !sizeElem.isNull() )
2712 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2721 const QString &path,
const QString &format,
int *markIndex,
2722 const QColor &color,
double size )
2730 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2731 element.appendChild( markElem );
2737 QDomElement markIndexElem = doc.createElement( QStringLiteral(
"se:MarkIndex" ) );
2738 markIndexElem.appendChild( doc.createTextNode( QString::number( *markIndex ) ) );
2739 markElem.appendChild( markIndexElem );
2743 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2744 fillToSld( doc, fillElem, context, Qt::SolidPattern, color );
2745 markElem.appendChild( fillElem );
2750 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2752 element.appendChild( sizeElem );
2757 QString &path, QString &format,
int &markIndex,
2758 QColor &color,
double &size )
2766 QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2767 if ( markElem.isNull() )
2772 const QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
2773 if ( !markIndexElem.isNull() )
2776 const int i = markIndexElem.firstChild().nodeValue().toInt( &ok );
2782 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2783 Qt::BrushStyle b = Qt::SolidPattern;
2788 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2789 if ( !sizeElem.isNull() )
2792 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2801 const QString &name,
const QColor &color,
const QColor &strokeColor, Qt::PenStyle strokeStyle,
2802 double strokeWidth,
double size )
2805 wellKnownMarkerToSld( doc, element, name, color, strokeColor, strokeStyle, context, strokeWidth, size );
2810 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2811 element.appendChild( markElem );
2813 QDomElement wellKnownNameElem = doc.createElement( QStringLiteral(
"se:WellKnownName" ) );
2814 wellKnownNameElem.appendChild( doc.createTextNode( name ) );
2815 markElem.appendChild( wellKnownNameElem );
2818 if ( color.isValid() )
2820 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2821 fillToSld( doc, fillElem, context, Qt::SolidPattern, color );
2822 markElem.appendChild( fillElem );
2826 if ( strokeColor.isValid() )
2828 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
2829 lineToSld( doc, strokeElem, strokeStyle, strokeColor, context, strokeWidth );
2830 markElem.appendChild( strokeElem );
2836 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2838 element.appendChild( sizeElem );
2843 QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle,
2844 double &strokeWidth,
double &size )
2848 name = QStringLiteral(
"square" );
2850 strokeColor = QColor( 0, 0, 0 );
2854 const QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2855 if ( markElem.isNull() )
2858 const QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
2859 if ( !wellKnownNameElem.isNull() )
2861 name = wellKnownNameElem.firstChild().nodeValue();
2866 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2867 Qt::BrushStyle b = Qt::SolidPattern;
2872 QDomElement strokeElem = markElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2873 lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth );
2877 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2878 if ( !sizeElem.isNull() )
2881 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2897 if ( !rotationFunc.isEmpty() )
2899 QDomElement rotationElem = doc.createElement( QStringLiteral(
"se:Rotation" ) );
2901 element.appendChild( rotationElem );
2907 QDomElement rotationElem = element.firstChildElement( QStringLiteral(
"Rotation" ) );
2908 if ( !rotationElem.isNull() )
2923 if ( !alphaFunc.isEmpty() )
2925 QDomElement opacityElem = doc.createElement( QStringLiteral(
"se:Opacity" ) );
2927 element.appendChild( opacityElem );
2933 QDomElement opacityElem = element.firstChildElement( QStringLiteral(
"Opacity" ) );
2934 if ( !opacityElem.isNull() )
2943 if ( offset.isNull() )
2946 QDomElement displacementElem = doc.createElement( QStringLiteral(
"se:Displacement" ) );
2947 element.appendChild( displacementElem );
2949 QDomElement dispXElem = doc.createElement( QStringLiteral(
"se:DisplacementX" ) );
2950 dispXElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.x(), 2 ) ) );
2952 QDomElement dispYElem = doc.createElement( QStringLiteral(
"se:DisplacementY" ) );
2953 dispYElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.y(), 2 ) ) );
2955 displacementElem.appendChild( dispXElem );
2956 displacementElem.appendChild( dispYElem );
2963 QDomElement anchorElem = doc.createElement( QStringLiteral(
"se:AnchorPoint" ) );
2964 element.appendChild( anchorElem );
2966 QDomElement anchorXElem = doc.createElement( QStringLiteral(
"se:AnchorPointX" ) );
2967 anchorXElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.x() ) ) );
2969 QDomElement anchorYElem = doc.createElement( QStringLiteral(
"se:AnchorPointY" ) );
2970 anchorYElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.y() ) ) );
2972 anchorElem.appendChild( anchorXElem );
2973 anchorElem.appendChild( anchorYElem );
2978 offset = QPointF( 0, 0 );
2980 const QDomElement displacementElem = element.firstChildElement( QStringLiteral(
"Displacement" ) );
2981 if ( displacementElem.isNull() )
2984 const QDomElement dispXElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementX" ) );
2985 if ( !dispXElem.isNull() )
2988 const double offsetX = dispXElem.firstChild().nodeValue().toDouble( &ok );
2990 offset.setX( offsetX );
2993 const QDomElement dispYElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementY" ) );
2994 if ( !dispYElem.isNull() )
2997 const double offsetY = dispYElem.firstChild().nodeValue().toDouble( &ok );
2999 offset.setY( offsetY );
3006 const QString &label,
const QFont &font,
3007 const QColor &color,
double size )
3010 labelTextToSld( doc, element, label, font, context, color, size );
3015 QDomElement labelElem = doc.createElement( QStringLiteral(
"se:Label" ) );
3016 labelElem.appendChild( doc.createTextNode( label ) );
3017 element.appendChild( labelElem );
3019 QDomElement fontElem = doc.createElement( QStringLiteral(
"se:Font" ) );
3020 element.appendChild( fontElem );
3024 fontElem.appendChild( createSldParameterElement( doc,
"font-style",
encodeSldFontStyle( font.style() ) ) );
3025 fontElem.appendChild( createSldParameterElement( doc,
"font-weight",
encodeSldFontWeight( font.weight() ) ) );
3030 if ( color.isValid() )
3032 QDomElement fillElem = doc.createElement( QStringLiteral(
"Fill" ) );
3033 fillToSld( doc, fillElem, context, Qt::SolidPattern, color );
3034 element.appendChild( fillElem );
3039 Qt::PenJoinStyle joinStyle,
3040 Qt::PenCapStyle capStyle,
3042 const QVector<qreal> *dashPattern )
3045 penStyle.append(
"PEN(" );
3046 penStyle.append(
"c:" );
3047 penStyle.append(
c.name() );
3048 penStyle.append(
",w:" );
3050 penStyle.append( QString::number( width * mmScaleFactor ) );
3051 penStyle.append(
"mm" );
3054 if ( dashPattern && !dashPattern->isEmpty() )
3056 penStyle.append(
",p:\"" );
3057 QVector<qreal>::const_iterator pIt = dashPattern->constBegin();
3058 for ( ; pIt != dashPattern->constEnd(); ++pIt )
3060 if ( pIt != dashPattern->constBegin() )
3062 penStyle.append(
' ' );
3064 penStyle.append( QString::number( *pIt * mapUnitScaleFactor ) );
3065 penStyle.append(
'g' );
3067 penStyle.append(
'\"' );
3071 penStyle.append(
",cap:" );
3075 penStyle.append(
'p' );
3078 penStyle.append(
'r' );
3082 penStyle.append(
'b' );
3086 penStyle.append(
",j:" );
3087 switch ( joinStyle )
3090 penStyle.append(
'b' );
3093 penStyle.append(
'r' );
3097 penStyle.append(
'm' );
3103 penStyle.append(
",dp:" );
3104 penStyle.append( QString::number( offset * mapUnitScaleFactor ) );
3105 penStyle.append(
'g' );
3108 penStyle.append(
')' );
3115 brushStyle.append(
"BRUSH(" );
3116 brushStyle.append(
"fc:" );
3117 brushStyle.append( fillColor.name() );
3118 brushStyle.append(
')' );
3130 if ( geomFunc.isEmpty() )
3133 QDomElement geometryElem = doc.createElement( QStringLiteral(
"Geometry" ) );
3134 element.appendChild( geometryElem );
3164 QDomElement geometryElem = element.firstChildElement( QStringLiteral(
"Geometry" ) );
3165 if ( geometryElem.isNull() )
3183 context.
pushError( QObject::tr(
"Parser error encountered when converting expression to SLD: %1 - Expression was: %2" ).arg( expr.
parserErrorString(), function ) );
3187 if ( !filterElem.isNull() )
3188 element.appendChild( filterElem );
3201 if ( function == QLatin1String(
"ELSE" ) )
3204 element.appendChild( filterElem );
3213 context.
pushError( QObject::tr(
"Parser error encountered when converting expression to SLD: %1 - Expression was: %2" ).arg( expr.
parserErrorString(), function ) );
3217 if ( !filterElem.isNull() )
3218 element.appendChild( filterElem );
3226 QDomElement elem = element;
3227 if ( element.tagName() != QLatin1String(
"Filter" ) )
3229 const QDomNodeList filterNodes = element.elementsByTagName( QStringLiteral(
"Filter" ) );
3230 if ( !filterNodes.isEmpty() )
3232 elem = filterNodes.at( 0 ).toElement();
3236 if ( elem.isNull() )
3261 const QString &path,
const QString &format )
3265 QDomElement onlineResourceElem = doc.createElement( QStringLiteral(
"se:OnlineResource" ) );
3266 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
3267 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:href" ), url );
3268 element.appendChild( onlineResourceElem );
3270 QDomElement formatElem = doc.createElement( QStringLiteral(
"se:Format" ) );
3271 formatElem.appendChild( doc.createTextNode( format ) );
3272 element.appendChild( formatElem );
3279 const QDomElement onlineResourceElem = element.firstChildElement( QStringLiteral(
"OnlineResource" ) );
3280 if ( onlineResourceElem.isNull() )
3283 path = QUrl::fromPercentEncoding( onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) ).toUtf8() );
3285 const QDomElement formatElem = element.firstChildElement( QStringLiteral(
"Format" ) );
3286 if ( formatElem.isNull() )
3289 format = formatElem.firstChild().nodeValue();
3296 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:SvgParameter" ) );
3297 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
3298 nodeElem.appendChild( doc.createTextNode( value ) );
3307 QDomElement paramElem = element.firstChildElement();
3308 while ( !paramElem.isNull() )
3310 if ( paramElem.localName() == QLatin1String(
"SvgParameter" ) || paramElem.localName() == QLatin1String(
"CssParameter" ) )
3312 const QString name = paramElem.attribute( QStringLiteral(
"name" ) );
3313 if ( paramElem.firstChild().nodeType() == QDomNode::TextNode )
3315 value = paramElem.firstChild().nodeValue();
3319 if ( paramElem.firstChild().nodeType() == QDomNode::ElementNode &&
3320 paramElem.firstChild().localName() == QLatin1String(
"Literal" ) )
3323 value = paramElem.firstChild().firstChild().nodeValue();
3327 QgsDebugError( QStringLiteral(
"unexpected child of %1" ).arg( paramElem.localName() ) );
3331 if ( !name.isEmpty() && !value.isEmpty() )
3332 params[ name ] = value;
3335 paramElem = paramElem.nextSiblingElement();
3343 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:VendorOption" ) );
3344 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
3345 nodeElem.appendChild( doc.createTextNode( value ) );
3353 QDomElement paramElem = element.firstChildElement( QStringLiteral(
"VendorOption" ) );
3354 while ( !paramElem.isNull() )
3356 const QString name = paramElem.attribute( QStringLiteral(
"name" ) );
3357 const QString value = paramElem.firstChild().nodeValue();
3359 if ( !name.isEmpty() && !value.isEmpty() )
3360 params[ name ] = value;
3362 paramElem = paramElem.nextSiblingElement( QStringLiteral(
"VendorOption" ) );
3372 if ( newSymbols.userType() == QMetaType::Type::QVariantMap )
3374 return newSymbols.toMap();
3381 QDomElement e = element.firstChildElement();
3382 while ( !e.isNull() )
3384 if ( e.tagName() == QLatin1String(
"prop" ) )
3386 const QString propKey = e.attribute( QStringLiteral(
"k" ) );
3387 const QString propValue = e.attribute( QStringLiteral(
"v" ) );
3388 props[propKey] = propValue;
3390 e = e.nextSiblingElement();
3407 QDomElement e = element.firstChildElement();
3409 while ( !e.isNull() )
3411 if ( e.tagName() == QLatin1String(
"symbol" ) )
3415 symbols.insert( e.attribute( QStringLiteral(
"name" ) ), symbol.release() );
3421 e = e.nextSiblingElement();
3428 QStringList subsymbols;
3430 for ( QMap<QString, QgsSymbol *>::iterator it = symbols.begin(); it != symbols.end(); ++it )
3432 if ( it.key()[0] !=
'@' )
3436 subsymbols.append( it.key() );
3438 QStringList parts = it.key().split(
'@' );
3439 if ( parts.count() < 3 )
3441 QgsDebugError(
"found subsymbol with invalid name: " + it.key() );
3445 const QString symname = parts[1];
3446 const int symlayer = parts[2].toInt();
3448 if ( !symbols.contains( symname ) )
3450 QgsDebugError(
"subsymbol references invalid symbol: " + symname );
3458 QgsDebugError(
"subsymbol references invalid symbol layer: " + QString::number( symlayer ) );
3467 QgsDebugError(
"symbol layer refused subsymbol: " + it.key() );
3474 for (
int i = 0; i < subsymbols.count(); i++ )
3475 symbols.take( subsymbols[i] );
3482 QDomElement symbolsElem = doc.createElement( tagName );
3485 for ( QMap<QString, QgsSymbol *>::iterator its = symbols.begin(); its != symbols.end(); ++its )
3487 const QDomElement symEl =
saveSymbol( its.key(), its.value(), doc, context );
3488 symbolsElem.appendChild( symEl );
3496 qDeleteAll( symbols );
3505 std::unique_ptr< QMimeData >mimeData(
new QMimeData );
3507 QDomDocument symbolDoc;
3509 symbolDoc.appendChild( symbolElem );
3510 mimeData->setText( symbolDoc.toString() );
3513 mimeData->setColorData( symbol->
color() );
3515 return mimeData.release();
3523 const QString text = data->text();
3524 if ( !text.isEmpty() )
3529 if ( doc.setContent( text ) )
3531 elem = doc.documentElement();
3533 if ( elem.nodeName() != QLatin1String(
"symbol" ) )
3534 elem = elem.firstChildElement( QStringLiteral(
"symbol" ) );
3545 const QString rampType = element.attribute( QStringLiteral(
"type" ) );
3570 QDomElement rampEl = doc.createElement( QStringLiteral(
"colorramp" ) );
3571 rampEl.setAttribute( QStringLiteral(
"type" ), ramp->
type() );
3572 rampEl.setAttribute( QStringLiteral(
"name" ), name );
3580 QVariantMap rampMap;
3582 rampMap.insert( QStringLiteral(
"type" ), ramp->
type() );
3583 rampMap.insert( QStringLiteral(
"name" ), name );
3585 const QVariantMap properties = ramp->
properties();
3587 QVariantMap propertyMap;
3588 for (
auto property = properties.constBegin();
property != properties.constEnd(); ++property )
3590 propertyMap.insert( property.key(),
property.value() );
3593 rampMap.insert( QStringLiteral(
"properties" ), propertyMap );
3599 const QVariantMap rampMap = value.toMap();
3601 const QString rampType = rampMap.value( QStringLiteral(
"type" ) ).toString();
3604 const QVariantMap propertyMap = rampMap.value( QStringLiteral(
"properties" ) ).toMap();
3607 for (
auto property = propertyMap.constBegin();
property != propertyMap.constEnd(); ++property )
3609 props.insert( property.key(),
property.value().toString() );
3631 if ( !color.isValid() )
3638 return color.name();
3643 QList<QColor> colors;
3646 const thread_local QRegularExpression sepCommaSpaceRegExp(
"(,|\\s)" );
3647 QStringList components = colorStr.simplified().split( sepCommaSpaceRegExp );
3648 QStringList::iterator it = components.begin();
3649 for ( ; it != components.end(); ++it )
3651 const QColor result =
parseColor( *it,
true );
3652 if ( result.isValid() )
3657 if ( colors.length() > 0 )
3663 const thread_local QRegularExpression sepCommaRegExp(
"(,|\n)" );
3664 components = colorStr.split( sepCommaRegExp );
3665 it = components.begin();
3666 for ( ; it != components.end(); ++it )
3668 const QColor result =
parseColor( *it,
true );
3669 if ( result.isValid() )
3674 if ( colors.length() > 0 )
3680 components = colorStr.simplified().split( QString(
' ' ) );
3681 it = components.begin();
3682 for ( ; it != components.end(); ++it )
3684 const QColor result =
parseColor( *it,
true );
3685 if ( result.isValid() )
3690 if ( colors.length() > 0 )
3696 components = colorStr.split(
'\n' );
3697 it = components.begin();
3698 for ( ; it != components.end(); ++it )
3700 const QColor result =
parseColor( *it,
true );
3701 if ( result.isValid() )
3714 QMimeData *mimeData =
new QMimeData;
3715 mimeData->setColorData( QVariant( color ) );
3716 mimeData->setText( color.name() );
3726 if ( mimeData->hasColor() )
3728 QColor mimeColor = mimeData->colorData().value<QColor>();
3729 if ( mimeColor.isValid() )
3737 if ( mimeData->hasText() )
3741 if ( textColor.isValid() )
3759 if ( data->hasFormat( QStringLiteral(
"text/xml" ) ) )
3762 const QByteArray encodedData = data->data( QStringLiteral(
"text/xml" ) );
3763 QDomDocument xmlDoc;
3764 xmlDoc.setContent( encodedData );
3766 const QDomElement dragDataElem = xmlDoc.documentElement();
3767 if ( dragDataElem.tagName() == QLatin1String(
"ColorSchemeModelDragData" ) )
3769 const QDomNodeList nodeList = dragDataElem.childNodes();
3770 const int nChildNodes = nodeList.size();
3771 QDomElement currentElem;
3773 for (
int i = 0; i < nChildNodes; ++i )
3775 currentElem = nodeList.at( i ).toElement();
3776 if ( currentElem.isNull() )
3781 QPair< QColor, QString> namedColor;
3783 namedColor.second = currentElem.attribute( QStringLiteral(
"label" ), QString() );
3785 mimeColors << namedColor;
3790 if ( mimeColors.length() == 0 && data->hasFormat( QStringLiteral(
"application/x-colorobject-list" ) ) )
3793 const QByteArray encodedData = data->data( QStringLiteral(
"application/x-colorobject-list" ) );
3794 QDomDocument xmlDoc;
3795 xmlDoc.setContent( encodedData );
3797 const QDomNodeList colorsNodes = xmlDoc.elementsByTagName( QStringLiteral(
"colors" ) );
3798 if ( colorsNodes.length() > 0 )
3800 const QDomElement colorsElem = colorsNodes.at( 0 ).toElement();
3801 const QDomNodeList colorNodeList = colorsElem.childNodes();
3802 const int nChildNodes = colorNodeList.size();
3803 QDomElement currentElem;
3805 for (
int i = 0; i < nChildNodes; ++i )
3808 currentElem = colorNodeList.at( i ).toElement();
3809 if ( currentElem.isNull() )
3814 const QDomNodeList colorNodes = currentElem.elementsByTagName( QStringLiteral(
"color" ) );
3815 const QDomNodeList nameNodes = currentElem.elementsByTagName( QStringLiteral(
"name" ) );
3817 if ( colorNodes.length() > 0 )
3819 const QDomElement colorElem = colorNodes.at( 0 ).toElement();
3821 const QStringList colorParts = colorElem.text().simplified().split(
' ' );
3822 if ( colorParts.length() < 3 )
3827 const int red = colorParts.at( 0 ).toDouble() * 255;
3828 const int green = colorParts.at( 1 ).toDouble() * 255;
3829 const int blue = colorParts.at( 2 ).toDouble() * 255;
3830 QPair< QColor, QString> namedColor;
3831 namedColor.first = QColor( red, green, blue );
3832 if ( nameNodes.length() > 0 )
3834 const QDomElement nameElem = nameNodes.at( 0 ).toElement();
3835 namedColor.second = nameElem.text();
3837 mimeColors << namedColor;
3843 if ( mimeColors.length() == 0 && data->hasText() )
3847 QList< QColor >::iterator it = parsedColors.begin();
3848 for ( ; it != parsedColors.end(); ++it )
3850 mimeColors << qMakePair( *it, QString() );
3854 if ( mimeColors.length() == 0 && data->hasColor() )
3857 const QColor mimeColor = data->colorData().value<QColor>();
3858 if ( mimeColor.isValid() )
3860 mimeColors << qMakePair( mimeColor, QString() );
3870 QMimeData *mimeData =
new QMimeData();
3871 QDomDocument xmlDoc;
3872 QDomElement xmlRootElement = xmlDoc.createElement( QStringLiteral(
"ColorSchemeModelDragData" ) );
3873 xmlDoc.appendChild( xmlRootElement );
3875 QgsNamedColorList::const_iterator colorIt = colorList.constBegin();
3876 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3878 QDomElement namedColor = xmlDoc.createElement( QStringLiteral(
"NamedColor" ) );
3880 namedColor.setAttribute( QStringLiteral(
"label" ), ( *colorIt ).second );
3881 xmlRootElement.appendChild( namedColor );
3883 mimeData->setData( QStringLiteral(
"text/xml" ), xmlDoc.toByteArray() );
3891 colorIt = colorList.constBegin();
3892 QStringList colorListString;
3893 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3895 colorListString << ( *colorIt ).first.name();
3897 mimeData->setText( colorListString.join( QLatin1Char(
'\n' ) ) );
3900 if ( colorList.length() > 0 )
3902 mimeData->setColorData( QVariant( colorList.at( 0 ).first ) );
3910 if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3915 QTextStream stream( &file );
3916#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
3917 stream.setCodec(
"UTF-8" );
3920 stream <<
"GIMP Palette" << Qt::endl;
3921 if ( paletteName.isEmpty() )
3923 stream <<
"Name: QGIS Palette" << Qt::endl;
3927 stream <<
"Name: " << paletteName << Qt::endl;
3929 stream <<
"Columns: 4" << Qt::endl;
3930 stream <<
'#' << Qt::endl;
3932 for ( QgsNamedColorList::ConstIterator colorIt = colors.constBegin(); colorIt != colors.constEnd(); ++colorIt )
3934 const QColor color = ( *colorIt ).first;
3935 if ( !color.isValid() )
3939 stream << QStringLiteral(
"%1 %2 %3" ).arg( color.red(), 3 ).arg( color.green(), 3 ).arg( color.blue(), 3 );
3940 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << Qt::endl;
3951 if ( !file.open( QIODevice::ReadOnly ) )
3954 return importedColors;
3957 QTextStream in( &file );
3958#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
3959 in.setCodec(
"UTF-8" );
3962 QString line = in.readLine();
3963 if ( !line.startsWith( QLatin1String(
"GIMP Palette" ) ) )
3966 return importedColors;
3970 while ( !in.atEnd() && !line.startsWith( QLatin1String(
"Name:" ) ) && !line.startsWith(
'#' ) )
3972 line = in.readLine();
3974 if ( line.startsWith( QLatin1String(
"Name:" ) ) )
3976 const thread_local QRegularExpression nameRx(
"Name:\\s*(\\S.*)$" );
3977 const QRegularExpressionMatch match = nameRx.match( line );
3978 if ( match.hasMatch() )
3980 name = match.captured( 1 );
3985 while ( !in.atEnd() && !line.startsWith(
'#' ) )
3987 line = in.readLine();
3992 return importedColors;
3996 const thread_local QRegularExpression rx(
"^\\s*(\\d+)\\s+(\\d+)\\s+(\\d+)(\\s.*)?$" );
3997 while ( !in.atEnd() )
3999 line = in.readLine();
4000 const QRegularExpressionMatch match = rx.match( line );
4001 if ( !match.hasMatch() )
4005 const int red = match.captured( 1 ).toInt();
4006 const int green = match.captured( 2 ).toInt();
4007 const int blue = match.captured( 3 ).toInt();
4008 const QColor color = QColor( red, green, blue );
4009 if ( !color.isValid() )
4016 if ( rx.captureCount() > 3 )
4018 label = match.captured( 4 ).simplified();
4025 importedColors << qMakePair( color, label );
4030 return importedColors;
4043 const thread_local QRegularExpression hexColorAlphaRx(
"^\\s*#?([0-9a-fA-F]{6})([0-9a-fA-F]{2})\\s*$" );
4044 QRegularExpressionMatch match = hexColorAlphaRx.match( colorStr );
4047 if ( !match.hasMatch() && QColor::isValidColor( colorStr ) )
4050 parsedColor.setNamedColor( colorStr );
4051 if ( parsedColor.isValid() )
4053 containsAlpha =
false;
4059 if ( match.hasMatch() )
4061 const QString hexColor = match.captured( 1 );
4062 parsedColor.setNamedColor( QStringLiteral(
"#" ) + hexColor );
4064 const int alphaHex = match.captured( 2 ).toInt( &alphaOk, 16 );
4066 if ( parsedColor.isValid() && alphaOk )
4068 parsedColor.setAlpha( alphaHex );
4069 containsAlpha =
true;
4077 const thread_local QRegularExpression hexColorRx2(
"^\\s*(?:[0-9a-fA-F]{3}){1,2}\\s*$" );
4078 if ( colorStr.indexOf( hexColorRx2 ) != -1 )
4081 parsedColor.setNamedColor( QStringLiteral(
"#" ) + colorStr );
4082 if ( parsedColor.isValid() )
4084 containsAlpha =
false;
4091 const thread_local QRegularExpression rgbFormatRx(
"^\\s*(?:rgb)?\\(?\\s*((?:[01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])(?:\\.\\d*)?)\\s*,\\s*((?:[01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])(?:\\.\\d*)?)\\s*,\\s*((?:[01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])(?:\\.\\d*)?)\\s*\\)?\\s*;?\\s*$" );
4092 match = rgbFormatRx.match( colorStr );
4093 if ( match.hasMatch() )
4098 const int r = match.captured( 1 ).toInt( &rOk );
4099 const int g = match.captured( 2 ).toInt( &gOk );
4100 const int b = match.captured( 3 ).toInt( &bOk );
4102 if ( !rOk || !gOk || !bOk )
4104 const float rFloat = match.captured( 1 ).toFloat();
4105 const float gFloat = match.captured( 2 ).toFloat();
4106 const float bFloat = match.captured( 3 ).toFloat();
4107 parsedColor.setRgbF( rFloat / 255.0, gFloat / 255.0, bFloat / 255.0 );
4111 parsedColor.setRgb( r, g, b );
4114 if ( parsedColor.isValid() )
4116 containsAlpha =
false;
4122 const thread_local QRegularExpression hslFormatRx(
"^\\s*hsl\\(?\\s*(\\d+(?:\\.\\d*)?)\\s*,\\s*(\\d+(?:\\.\\d*)?)\\s*%\\s*,\\s*(\\d+(?:\\.\\d*)?)\\s*%\\s*\\)?\\s*;?\\s*$" );
4123 match = hslFormatRx.match( colorStr );
4124 if ( match.hasMatch() )
4129 const int h = match.captured( 1 ).toInt( &hOk );
4130 const int s = match.captured( 2 ).toInt( &sOk );
4131 const int l = match.captured( 3 ).toInt( &lOk );
4133 if ( !hOk || !sOk || !lOk )
4135 const float hFloat = match.captured( 1 ).toFloat();
4136 const float sFloat = match.captured( 2 ).toFloat();
4137 const float lFloat = match.captured( 3 ).toFloat();
4138 parsedColor.setHslF( hFloat / 360.0, sFloat / 100.0, lFloat / 100.0 );
4142 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0 );
4144 if ( parsedColor.isValid() )
4146 containsAlpha =
false;
4152 const thread_local QRegularExpression rgbPercentFormatRx(
"^\\s*(?:rgb)?\\(?\\s*(100|0*\\d{1,2}(?:\\.\\d*)?)\\s*%\\s*,\\s*(100|0*\\d{1,2}(?:\\.\\d*)?)\\s*%\\s*,\\s*(100|0*\\d{1,2}(?:\\.\\d*)?)\\s*%\\s*\\)?\\s*;?\\s*$" );
4153 match = rgbPercentFormatRx.match( colorStr );
4154 if ( match.hasMatch() )
4156 const double r = match.captured( 1 ).toDouble() / 100;
4157 const double g = match.captured( 2 ).toDouble() / 100;
4158 const double b = match.captured( 3 ).toDouble() / 100;
4159 parsedColor.setRgbF( r, g, b );
4160 if ( parsedColor.isValid() )
4162 containsAlpha =
false;
4168 const thread_local QRegularExpression rgbaFormatRx(
"^\\s*(?:rgba)?\\(?\\s*((?:[01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])(?:\\.\\d*)?)\\s*,\\s*((?:[01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])(?:\\.\\d*)?)\\s*,\\s*((?:[01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])(?:\\.\\d*)?)\\s*,\\s*(0|0?\\.\\d*|1(?:\\.0*)?)\\s*\\)?\\s*;?\\s*$" );
4169 match = rgbaFormatRx.match( colorStr );
4170 if ( match.hasMatch() )
4175 const int r = match.captured( 1 ).toInt( &rOk );
4176 const int g = match.captured( 2 ).toInt( &gOk );
4177 const int b = match.captured( 3 ).toInt( &bOk );
4178 const double aDouble = match.captured( 4 ).toDouble();
4180 if ( !rOk || !gOk || !bOk )
4182 const float rFloat = match.captured( 1 ).toFloat();
4183 const float gFloat = match.captured( 2 ).toFloat();
4184 const float bFloat = match.captured( 3 ).toFloat();
4185 parsedColor.setRgbF( rFloat / 255.0, gFloat / 255.0, bFloat / 255.0, aDouble );
4189 const int a =
static_cast< int >( std::round( match.captured( 4 ).toDouble() * 255.0 ) );
4190 parsedColor.setRgb( r, g, b, a );
4192 if ( parsedColor.isValid() )
4194 containsAlpha =
true;
4200 const thread_local QRegularExpression rgbaPercentFormatRx(
"^\\s*(?:rgba)?\\(?\\s*(100|0*\\d{1,2}(?:\\.\\d*)?)\\s*%\\s*,\\s*(100|0*\\d{1,2}(?:\\.\\d*)?)\\s*%\\s*,\\s*(100|0*\\d{1,2}(?:\\.\\d*)?)\\s*%\\s*,\\s*(0|0?\\.\\d*|1(?:\\.0*)?)\\s*\\)?\\s*;?\\s*$" );
4201 match = rgbaPercentFormatRx.match( colorStr );
4202 if ( match.hasMatch() )
4204 const double r = match.captured( 1 ).toDouble() / 100;
4205 const double g = match.captured( 2 ).toDouble() / 100;
4206 const double b = match.captured( 3 ).toDouble() / 100;
4207 const double a = match.captured( 4 ).toDouble();
4208 parsedColor.setRgbF( r, g, b, a );
4209 if ( parsedColor.isValid() )
4211 containsAlpha =
true;
4217 const thread_local QRegularExpression hslaPercentFormatRx(
"^\\s*hsla\\(?\\s*(\\d+(?:\\.\\d*)?)\\s*,\\s*(\\d+(?:\\.\\d*)?)\\s*%\\s*,\\s*(\\d+(?:\\.\\d*)?)\\s*%\\s*,\\s*([\\d\\.]+)\\s*\\)?\\s*;?\\s*$" );
4218 match = hslaPercentFormatRx.match( colorStr );
4219 if ( match.hasMatch() )
4224 const int h = match.captured( 1 ).toInt( &hOk );
4225 const int s = match.captured( 2 ).toInt( &sOk );
4226 const int l = match.captured( 3 ).toInt( &lOk );
4227 const double aDouble = match.captured( 4 ).toDouble();
4229 if ( !hOk || !sOk || !lOk )
4231 const float hFloat = match.captured( 1 ).toFloat();
4232 const float sFloat = match.captured( 2 ).toFloat();
4233 const float lFloat = match.captured( 3 ).toFloat();
4234 parsedColor.setHslF( hFloat / 360.0, sFloat / 100.0, lFloat / 100.0, aDouble );
4238 const int a = std::round( aDouble * 255.0 );
4239 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0, a );
4242 if ( parsedColor.isValid() )
4244 containsAlpha =
true;
4261 const QImage::Format format = image->format();
4262 if ( format != QImage::Format_ARGB32_Premultiplied && format != QImage::Format_ARGB32 )
4269 for (
int heightIndex = 0; heightIndex < image->height(); ++heightIndex )
4271 QRgb *scanLine =
reinterpret_cast< QRgb *
>( image->scanLine( heightIndex ) );
4272 for (
int widthIndex = 0; widthIndex < image->width(); ++widthIndex )
4274 myRgb = scanLine[widthIndex];
4275 if ( format == QImage::Format_ARGB32_Premultiplied )
4276 scanLine[widthIndex] = qRgba( opacity * qRed( myRgb ), opacity * qGreen( myRgb ), opacity * qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4278 scanLine[widthIndex] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4286 const int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
4287 const int alpha = ( radius < 1 ) ? 16 : ( radius > 17 ) ? 1 : tab[radius - 1];
4289 if ( image.format() != QImage::Format_ARGB32_Premultiplied
4290 && image.format() != QImage::Format_RGB32 )
4292 image = image.convertToFormat( QImage::Format_ARGB32_Premultiplied );
4295 const int r1 = rect.top();
4296 const int r2 = rect.bottom();
4297 const int c1 = rect.left();
4298 const int c2 = rect.right();
4300 const int bpl = image.bytesPerLine();
4308 i1 = i2 = ( QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3 );
4310 for (
int col = c1; col <= c2; col++ )
4312 p = image.scanLine( r1 ) + col * 4;
4313 for (
int i = i1; i <= i2; i++ )
4314 rgba[i] = p[i] << 4;
4317 for (
int j = r1; j < r2; j++, p += bpl )
4318 for (
int i = i1; i <= i2; i++ )
4319 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4322 for (
int row = r1; row <= r2; row++ )
4324 p = image.scanLine( row ) + c1 * 4;
4325 for (
int i = i1; i <= i2; i++ )
4326 rgba[i] = p[i] << 4;
4329 for (
int j = c1; j < c2; j++, p += 4 )
4330 for (
int i = i1; i <= i2; i++ )
4331 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4334 for (
int col = c1; col <= c2; col++ )
4336 p = image.scanLine( r2 ) + col * 4;
4337 for (
int i = i1; i <= i2; i++ )
4338 rgba[i] = p[i] << 4;
4341 for (
int j = r1; j < r2; j++, p -= bpl )
4342 for (
int i = i1; i <= i2; i++ )
4343 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4346 for (
int row = r1; row <= r2; row++ )
4348 p = image.scanLine( row ) + c2 * 4;
4349 for (
int i = i1; i <= i2; i++ )
4350 rgba[i] = p[i] << 4;
4353 for (
int j = c1; j < c2; j++, p -= 4 )
4354 for (
int i = i1; i <= i2; i++ )
4355 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4361 if ( alpha != 255 && alpha > 0 )
4365 const double alphaFactor = alpha / 255.;
4366 int r = 0, g = 0, b = 0;
4367 rgb.getRgb( &r, &g, &b );
4372 rgb.setRgb( r, g, b, alpha );
4374 else if ( alpha == 0 )
4376 rgb.setRgb( 0, 0, 0, 0 );
4385 if ( !simpleFill || !simpleLine )
4409 if ( simpleLine->
offset() )
4427 if ( order == Qt::AscendingOrder )
4441 const double dx = directionPoint.x() - startPoint.x();
4442 const double dy = directionPoint.y() - startPoint.y();
4443 const double length = std::sqrt( dx * dx + dy * dy );
4444 const double scaleFactor = distance / length;
4445 return QPointF( startPoint.x() + dx * scaleFactor, startPoint.y() + dy * scaleFactor );
4455 for (
int i = 0; i < svgPaths.size(); i++ )
4457 const QDir dir( svgPaths[i] );
4458 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4459 for (
const QString &item : svgSubPaths )
4461 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4464 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4465 for (
const QString &item : svgFiles )
4468 list.append( dir.path() +
'/' + item );
4480 QStringList svgPaths;
4481 svgPaths.append( directory );
4483 for (
int i = 0; i < svgPaths.size(); i++ )
4485 const QDir dir( svgPaths[i] );
4486 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4487 for (
const QString &item : svgSubPaths )
4489 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4492 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4493 for (
const QString &item : svgFiles )
4495 list.append( dir.path() +
'/' + item );
4507 if ( n.startsWith( QLatin1String(
"base64:" ) ) )
4511 if ( QFileInfo::exists( n ) )
4512 return QFileInfo( n ).canonicalFilePath();
4516 if ( name.contains( QLatin1String(
"://" ) ) )
4518 const QUrl url( name );
4519 if ( url.isValid() && !url.scheme().isEmpty() )
4521 if ( url.scheme().compare( QLatin1String(
"file" ), Qt::CaseInsensitive ) == 0 )
4524 name = url.toLocalFile();
4525 if ( QFile( name ).exists() )
4527 return QFileInfo( name ).canonicalFilePath();
4541 for (
int i = 0; i < svgPaths.size(); i++ )
4543 QString svgPath = svgPaths[i];
4544 if ( svgPath.endsWith( QChar(
'/' ) ) )
4555 const QString myLocalPath = svgPath + QDir::separator() + name;
4558 if ( QFile( myLocalPath ).exists() )
4561 return QFileInfo( myLocalPath ).canonicalFilePath();
4565 return pathResolver.
readPath( name );
4573 if ( p.startsWith( QLatin1String(
"base64:" ) ) )
4576 if ( !QFileInfo::exists( p ) )
4579 QString path = QFileInfo( p ).canonicalFilePath();
4583 bool isInSvgPaths =
false;
4584 for (
int i = 0; i < svgPaths.size(); i++ )
4586 const QString dir = QFileInfo( svgPaths[i] ).canonicalFilePath();
4588 if ( !dir.isEmpty() && path.startsWith( dir ) )
4590 path = path.mid( dir.size() + 1 );
4591 isInSvgPaths =
true;
4604 const double *srcX = line->
xData();
4605 const double *srcY = line->
yData();
4607 QPolygonF thisRes( count );
4608 QPointF *dest = thisRes.data();
4609 for (
int i = 0; i < count; ++i )
4611 *dest++ = QPointF( *srcX++, *srcY++ );
4618 if (
const QgsLineString *line = qgsgeometry_cast< const QgsLineString * >( curve ) )
4624 const std::unique_ptr< QgsLineString > straightened( curve->
curveToLine() );
4648 points << QPointF( ( *it ).x(), ( *it ).y() );
4652 points << QPointF( 0, 0 );
4654 return QList< QList<QPolygonF> >() << ( QList< QPolygonF >() << points );
4659 QList< QList<QPolygonF> > res;
4664 res << ( QList< QPolygonF >() <<
curveToPolygonF( qgsgeometry_cast< const QgsCurve * >( *it ) ) );
4672 QList< QList<QPolygonF> > res;
4676 QList<QPolygonF> thisPart;
4677 const QgsCurvePolygon *surface = qgsgeometry_cast< const QgsCurvePolygon * >( *it );
4695 return QList< QList<QPolygonF> >();
4698 return QList< QList<QPolygonF> >();
4705 double cx = 0, cy = 0;
4706 double area, sum = 0;
4707 for (
int i = points.count() - 1, j = 0; j < points.count(); i = j++ )
4709 const QPointF &p1 = points[i];
4710 const QPointF &p2 = points[j];
4711 area = p1.x() * p2.y() - p1.y() * p2.x();
4713 cx += ( p1.x() + p2.x() ) * area;
4714 cy += ( p1.y() + p2.y() ) * area;
4721 if ( points.count() >= 2 )
4722 return QPointF( ( points[0].x() + points[1].x() ) / 2, ( points[0].y() + points[1].y() ) / 2 );
4723 else if ( points.count() == 1 )
4731 return QPointF( cx, cy );
4738 if ( ( rings && rings->count() > 0 ) || !
pointInPolygon( points, centroid ) )
4740 unsigned int i, pointCount = points.count();
4742 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( points[i].x(), points[i].y() );
4748 for (
auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
4750 pointCount = ( *ringIt ).count();
4752 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( ( *ringIt )[i].x(), ( *ringIt )[i].y() );
4758 if ( !pointOnSurfaceGeom.
isNull() )
4761 centroid.
setX( point.
x() );
4762 centroid.setY( point.
y() );
4767 return QPointF( centroid.x(), centroid.y() );
4772 bool inside =
false;
4774 const double x = point.x();
4775 const double y = point.y();
4777 for (
int i = 0, j = points.count() - 1; i < points.count(); i++ )
4779 const QPointF &p1 = points[i];
4780 const QPointF &p2 = points[j];
4785 if ( ( p1.y() < y && p2.y() >= y ) || ( p2.y() < y && p1.y() >= y ) )
4787 if ( p1.x() + ( y - p1.y() ) / ( p2.y() - p1.y() ) * ( p2.x() - p1.x() ) <= x )
4798 if ( polyline.size() < 2 )
4801 double totalLength = 0;
4802 auto it = polyline.begin();
4804 for ( ; it != polyline.end(); ++it )
4806 const QPointF p2 = *it;
4807 const double segmentLength = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4808 totalLength += segmentLength;
4816 if ( polyline.size() < 2 )
4819 double totalLength = 0;
4820 auto it = polyline.begin();
4822 std::vector< double > segmentLengths( polyline.size() - 1 );
4823 auto segmentLengthIt = segmentLengths.begin();
4824 for ( ; it != polyline.end(); ++it )
4826 const QPointF p2 = *it;
4827 *segmentLengthIt = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4828 totalLength += *segmentLengthIt;
4834 if ( startOffset >= 0 && totalLength <= startOffset )
4836 if ( endOffset < 0 && totalLength <= -endOffset )
4839 const double startDistance = startOffset < 0 ? totalLength + startOffset : startOffset;
4840 const double endDistance = endOffset <= 0 ? totalLength + endOffset : endOffset;
4841 QPolygonF substringPoints;
4842 substringPoints.reserve( polyline.size() );
4844 it = polyline.begin();
4845 segmentLengthIt = segmentLengths.begin();
4848 bool foundStart =
false;
4849 if (
qgsDoubleNear( startDistance, 0.0 ) || startDistance < 0 )
4851 substringPoints << p1;
4855 double distanceTraversed = 0;
4856 for ( ; it != polyline.end(); ++it )
4858 const QPointF p2 = *it;
4859 if ( distanceTraversed < startDistance && distanceTraversed + *segmentLengthIt > startDistance )
4862 const double distanceToStart = startDistance - distanceTraversed;
4863 double startX, startY;
4865 substringPoints << QPointF( startX, startY );
4868 if ( foundStart && ( distanceTraversed + *segmentLengthIt > endDistance ) )
4871 const double distanceToEnd = endDistance - distanceTraversed;
4874 if ( substringPoints.last() != QPointF( endX, endY ) )
4875 substringPoints << QPointF( endX, endY );
4877 else if ( foundStart )
4879 if ( substringPoints.last() != QPointF( p2.x(), p2.y() ) )
4880 substringPoints << QPointF( p2.x(), p2.y() );
4883 distanceTraversed += *segmentLengthIt;
4884 if ( distanceTraversed > endDistance )
4891 if ( ( substringPoints.size() < 2 ) || ( substringPoints.size() == 2 && substringPoints.at( 0 ) == substringPoints.at( 1 ) ) )
4894 return substringPoints;
4899 double vertexAngle = M_PI - ( std::atan2( p3.y() - p2.y(), p3.x() - p2.x() ) - std::atan2( p2.y() - p1.y(), p2.x() - p1.x() ) );
4903 return vertexAngle < M_PI * 135.0 / 180.0 || vertexAngle > M_PI * 225.0 / 180.0;
4908 target.reserve( target.size() + line.size() );
4909 for (
const QPointF &pt : line )
4911 if ( !target.empty() && target.last() == pt )
4920 if ( fieldOrExpression.isEmpty() )
4923 auto expr = std::make_unique< QgsExpression >( fieldOrExpression );
4924 if ( !expr->hasParserError() )
4929 Q_ASSERT( !expr->hasParserError() );
4954 QList<double> breaks;
4957 breaks.append( maximum );
4961 const int minimumCount =
static_cast< int >( classes ) / 3;
4962 const double shrink = 0.75;
4963 const double highBias = 1.5;
4964 const double adjustBias = 0.5 + 1.5 * highBias;
4965 const int divisions = classes;
4966 const double h = highBias;
4969 const double dx = maximum - minimum;
4979 cell = std::max( std::fabs( minimum ), std::fabs( maximum ) );
4980 if ( adjustBias >= 1.5 * h + 0.5 )
4982 U = 1 + ( 1.0 / ( 1 + h ) );
4986 U = 1 + ( 1.5 / ( 1 + adjustBias ) );
4988 small = dx < ( cell * U * std::max( 1, divisions ) * 1e-07 * 3.0 );
4995 cell = 9 + cell / 10;
4996 cell = cell * shrink;
4998 if ( minimumCount > 1 )
5000 cell = cell / minimumCount;
5006 if ( divisions > 1 )
5008 cell = cell / divisions;
5011 if ( cell < 20 * 1e-07 )
5016 const double base = std::pow( 10.0, std::floor( std::log10( cell ) ) );
5018 if ( ( 2 * base ) - cell < h * ( cell - unit ) )
5021 if ( ( 5 * base ) - cell < adjustBias * ( cell - unit ) )
5024 if ( ( 10.0 * base ) - cell < h * ( cell - unit ) )
5031 int start = std::floor( minimum / unit + 1e-07 );
5032 int end = std::ceil( maximum / unit - 1e-07 );
5035 while ( start * unit > minimum + ( 1e-07 * unit ) )
5039 while ( end * unit < maximum - ( 1e-07 * unit ) )
5047 int k = std::floor( 0.5 + end - start );
5048 if ( k < minimumCount )
5050 k = minimumCount - k;
5054 start = start - k / 2 + k % 2;
5058 start = start - k / 2;
5059 end = end + k / 2 + k % 2;
5062 const double minimumBreak = start * unit;
5064 const int count = end - start;
5066 breaks.reserve( count );
5067 for (
int i = 1; i < count + 1; i++ )
5069 breaks.append( minimumBreak + i * unit );
5072 if ( breaks.isEmpty() )
5075 if ( breaks.first() < minimum )
5077 breaks[0] = minimum;
5079 if ( breaks.last() > maximum )
5081 breaks[breaks.count() - 1] = maximum;
5086 if ( minimum < 0.0 && maximum > 0.0 )
5088 QList<double> breaksMinusZero;
5089 for (
int i = 0; i < breaks.count(); i++ )
5091 breaksMinusZero.append( breaks[i] - 0.0 );
5094 for (
int i = 1; i < breaks.count(); i++ )
5096 if ( std::abs( breaksMinusZero[i] ) < std::abs( breaksMinusZero[i - 1] ) )
5099 breaks[posOfMin] = 0.0;
5108 bool roundToUnit =
false;
5111 if ( props.contains( QStringLiteral(
"uomScale" ) ) )
5114 scale = props.value( QStringLiteral(
"uomScale" ) ).toDouble( &ok );
5123 if ( props.value( QStringLiteral(
"uom" ) ) == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
5148 scale = 1 / 0.28 * 25.4;
5172 double rescaled = size * scale;
5177 rescaled = std::round( rescaled );
5184 const double x =
rescaleUom( point.x(), unit, props );
5185 const double y =
rescaleUom( point.y(), unit, props );
5186 return QPointF( x, y );
5191 QVector<qreal> result;
5192 QVector<qreal>::const_iterator it = array.constBegin();
5193 for ( ; it != array.constEnd(); ++it )
5195 result.append(
rescaleUom( *it, unit, props ) );
5202 if ( !props.value( QStringLiteral(
"scaleMinDenom" ), QString() ).toString().isEmpty() )
5204 QDomElement scaleMinDenomElem = doc.createElement( QStringLiteral(
"se:MinScaleDenominator" ) );
5205 scaleMinDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMinDenom" ) ).toString().toDouble() ) ) );
5206 ruleElem.appendChild( scaleMinDenomElem );
5209 if ( !props.value( QStringLiteral(
"scaleMaxDenom" ), QString() ).toString().isEmpty() )
5211 QDomElement scaleMaxDenomElem = doc.createElement( QStringLiteral(
"se:MaxScaleDenominator" ) );
5212 scaleMaxDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMaxDenom" ) ).toString().toDouble() ) ) );
5213 ruleElem.appendChild( scaleMaxDenomElem );
5222 const double parentScaleMinDenom = props.value( QStringLiteral(
"scaleMinDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
5223 if ( !ok || parentScaleMinDenom <= 0 )
5224 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( mScaleMinDenom );
5226 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( std::max( parentScaleMinDenom, mScaleMinDenom ) );
5232 const double parentScaleMaxDenom = props.value( QStringLiteral(
"scaleMaxDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
5233 if ( !ok || parentScaleMaxDenom <= 0 )
5234 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( mScaleMaxDenom );
5236 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( std::min( parentScaleMaxDenom, mScaleMaxDenom ) );
5244 if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
5246 scale = 1.0 / 0.00028;
5248 else if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
5250 scale = 304.8 / 0.28;
5257 return size * scale;
5266 SymbolLayerVisitor(
const QSet<QgsSymbolLayerId> &layerIds )
5267 : mSymbolLayerIds( layerIds )
5280 void visitSymbol(
const QgsSymbol *symbol,
const QString &identifier, QVector<int> rootPath )
5284 QVector<int> indexPath = rootPath;
5285 indexPath.append( idx );
5288 if ( mSymbolLayerIds.contains(
QgsSymbolLayerId( mCurrentRuleKey + identifier, indexPath ) ) )
5290 mSymbolLayers.insert( sl );
5296 visitSymbol( subSymbol, identifier, indexPath );
5305 if ( symbolEntity->symbol() )
5307 visitSymbol( symbolEntity->symbol(), leaf.
identifier, {} );
5313 QString mCurrentRuleKey;
5314 const QSet<QgsSymbolLayerId> &mSymbolLayerIds;
5315 QSet<const QgsSymbolLayer *> mSymbolLayers;
5319 SymbolLayerVisitor visitor( symbolLayerIds );
5320 renderer->
accept( &visitor );
5321 return visitor.mSymbolLayers;
5329 SymbolRefreshRateVisitor()
5341 void visitSymbol(
const QgsSymbol *symbol )
5358 if ( refreshRate == -1 || ( animatedMarker->frameRate() > refreshRate ) )
5359 refreshRate = animatedMarker->frameRate();
5363 visitSymbol( subSymbol );
5371 if (
QgsSymbol *symbol = qgis::down_cast<const QgsStyleSymbolEntity *>( leaf.
entity )->symbol() )
5373 visitSymbol( symbol );
5379 double refreshRate = -1;
5382 SymbolRefreshRateVisitor visitor;
5383 renderer->
accept( &visitor );
5384 return visitor.refreshRate;
5389 if ( !s || !context )
5415 size = markerSymbol->
size( *context );
5417 else if ( lineSymbol )
5419 size = lineSymbol->
width( *context );
5431 if ( minSize > 0 && size < minSize )
5435 else if ( maxSize > 0 && size > maxSize )
5454 else if ( lineSymbol )
5469 QMap<QString, QgsProperty>::const_iterator paramIt = propertiesMap.constBegin();
5470 for ( ; paramIt != propertiesMap.constEnd(); ++paramIt )
5472 properties.insert( paramIt.key(), paramIt.value().valueAsString( context ) );
5480 angleRad = std::fmod( angleRad, M_PI * 2 );
5484 angleRad += M_PI * 2;
5488 struct rationalTangent
5500 static const QList<rationalTangent> __rationalTangents
5502 { 1, 57, 0.01754206006 },
5503 { 3, 86, 0.03486958155 },
5504 { 1, 19, 0.05258306161 },
5505 { 3, 43, 0.06965457373 },
5506 { 7, 80, 0.08727771295 },
5507 { 2, 19, 0.1048769387 },
5508 { 7, 57, 0.1221951707 },
5509 { 9, 64, 0.1397088743 },
5510 { 13, 82, 0.157228051 },
5511 { 3, 17, 0.174672199 },
5512 { 7, 36, 0.1920480172 },
5513 { 17, 80, 0.209385393 },
5514 { 3, 13, 0.2267988481 },
5515 { 1, 4, 0.2449786631 },
5516 { 26, 97, 0.2618852647 },
5517 { 27, 94, 0.2797041525 },
5518 { 26, 85, 0.2968446734 },
5519 { 13, 40, 0.3142318991 },
5520 { 21, 61, 0.3315541619 },
5521 { 4, 11, 0.3487710036 },
5522 { 38, 99, 0.3664967859 },
5523 { 40, 99, 0.383984624 },
5524 { 31, 73, 0.4015805401 },
5525 { 41, 92, 0.4192323938 },
5526 { 7, 15, 0.4366271598 },
5527 { 20, 41, 0.4538440015 },
5528 { 27, 53, 0.4711662643 },
5529 { 42, 79, 0.4886424026 },
5530 { 51, 92, 0.5061751436 },
5531 { 56, 97, 0.5235757641 },
5532 { 3, 5, 0.5404195003 },
5533 { 5, 8, 0.5585993153 },
5534 { 50, 77, 0.5759185996 },
5535 { 29, 43, 0.5933501462 },
5536 { 7, 10, 0.6107259644 },
5537 { 69, 95, 0.6281701124 },
5538 { 52, 69, 0.6458159195 },
5539 { 25, 32, 0.6632029927 },
5540 { 17, 21, 0.6805212247 },
5541 { 73, 87, 0.6981204504 },
5542 { 73, 84, 0.7154487784 },
5543 { 9, 10, 0.7328151018 },
5544 { 83, 89, 0.7505285818 },
5545 { 28, 29, 0.7678561033 },
5546 { 1, 1, 0.7853981634 },
5547 { 29, 28, 0.8029402235 },
5548 { 89, 83, 0.820267745 },
5549 { 10, 9, 0.837981225 },
5550 { 107, 93, 0.855284165 },
5551 { 87, 73, 0.8726758763 },
5552 { 121, 98, 0.8900374031 },
5553 { 32, 25, 0.9075933341 },
5554 { 69, 52, 0.9249804073 },
5555 { 128, 93, 0.9424647244 },
5556 { 10, 7, 0.9600703624 },
5557 { 43, 29, 0.9774461806 },
5558 { 77, 50, 0.9948777272 },
5559 { 8, 5, 1.012197011 },
5560 { 163, 98, 1.029475114 },
5561 { 168, 97, 1.047174539 },
5562 { 175, 97, 1.064668696 },
5563 { 126, 67, 1.082075603 },
5564 { 157, 80, 1.099534652 },
5565 { 203, 99, 1.117049384 },
5566 { 193, 90, 1.134452855 },
5567 { 146, 65, 1.151936673 },
5568 { 139, 59, 1.169382787 },
5569 { 99, 40, 1.186811703 },
5570 { 211, 81, 1.204257817 },
5571 { 272, 99, 1.221730164 },
5572 { 273, 94, 1.239188479 },
5573 { 277, 90, 1.25664606 },
5574 { 157, 48, 1.274088705 },
5575 { 279, 80, 1.291550147 },
5576 { 362, 97, 1.308990773 },
5577 { 373, 93, 1.326448578 },
5578 { 420, 97, 1.343823596 },
5579 { 207, 44, 1.361353157 },
5580 { 427, 83, 1.378810994 },
5581 { 414, 73, 1.396261926 },
5582 { 322, 51, 1.413716057 },
5583 { 185, 26, 1.431170275 },
5584 { 790, 97, 1.448623034 },
5585 { 333, 35, 1.466075711 },
5586 { 1063, 93, 1.483530284 },
5587 { 1330, 93, 1.500985147 },
5588 { 706, 37, 1.518436297 },
5589 { 315, 11, 1.535889876 },
5590 { 3953, 69, 1.553343002 },
5596 static const QList<rationalTangent> rationalTangents
5598 { 1, 10, qDegreesToRadians( 5.71059 ) },
5599 { 1, 5, qDegreesToRadians( 11.3099 ) },
5600 { 1, 4, qDegreesToRadians( 14.0362 ) },
5601 { 1, 4, qDegreesToRadians( 18.4349 ) },
5602 { 1, 2, qDegreesToRadians( 26.5651 ) },
5603 { 2, 3, qDegreesToRadians( 33.6901 ) },
5604 { 1, 1, qDegreesToRadians( 45.0 ) },
5605 { 3, 2, qDegreesToRadians( 56.3099 ) },
5606 { 2, 1, qDegreesToRadians( 63.4349 ) },
5607 { 3, 1, qDegreesToRadians( 71.5651 ) },
5608 { 4, 1, qDegreesToRadians( 75.9638 ) },
5609 { 10, 1, qDegreesToRadians( 84.2894 ) },
5612 const int quadrant {
static_cast<int>( angleRad / M_PI_2 ) };
5613 Q_ASSERT( quadrant >= 0 && quadrant <= 3 );
5625 angleRad -= M_PI / 2;
5635 angleRad -= M_PI + M_PI_2;
5657 for (
int idx = 0; idx < rationalTangents.count(); ++idx )
5659 const auto item = rationalTangents.at( idx );
5660 if (
qgsDoubleNear( item.angle, angleRad, 10E-3 ) || item.angle > angleRad )
5667 const rationalTangent bTan { rationalTangents.at( rTanIdx ) };
5668 angleRad = bTan.angle;
5669 const double k { bTan.q *height *width / std::cos( angleRad ) };
5670 const int hcfH { std::gcd( bTan.p * height, bTan.q * width ) };
5671 const int hcfW { std::gcd( bTan.q * height, bTan.p * width ) };
5672 const int W1 {
static_cast<int>( std::round( k / hcfW ) ) };
5673 const int H1 {
static_cast<int>( std::round( k / hcfH ) ) };
5686 angleRad += M_PI / 2;
5699 angleRad += M_PI + M_PI_2;
5710template <
typename Functor>
5713 sl->
setId( generateId() );
5721template <
typename Functor>
5755 maskSl->clearMasks();
5758 if (
QgsSymbol *subSymbol = maskSl->subSymbol() )
5769 if ( clipGeometries.empty() )
5772 if ( bounds.isNull() )
5773 return clipGeometries;
5777 clipGeometries.erase(
5778 std::remove_if( clipGeometries.begin(), clipGeometries.end(), [&boundsRect](
const QgsGeometry & geometry )
5780 return !geometry.boundingBoxIntersects( boundsRect );
5781 } ), clipGeometries.end() );
5783 return clipGeometries;
@ PreferVector
Prefer vector-based rendering, when the result will still be visually near-identical to a raster-base...
MarkerClipMode
Marker clipping modes.
@ CompletelyWithin
Render complete markers wherever the completely fall within the polygon shape.
@ NoClipping
No clipping, render complete markers.
@ Shape
Clip to polygon shape.
@ CentroidWithin
Render complete markers wherever their centroid falls within the polygon shape.
LineClipMode
Line clipping modes.
@ NoClipping
Lines are not clipped, will extend to shape's bounding box.
@ ClipPainterOnly
Applying clipping on the painter only (i.e. line endpoints will coincide with polygon bounding box,...
@ ClipToIntersection
Clip lines to intersection with polygon shape (slower) (i.e. line endpoints will coincide with polygo...
ScaleMethod
Scale methods.
@ ScaleDiameter
Calculate scale by the diameter.
@ ScaleArea
Calculate scale by the area.
QFlags< SymbolLayerUserFlag > SymbolLayerUserFlags
Symbol layer user flags.
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
JoinStyle
Join styles for buffers.
@ Bevel
Use beveled joins.
@ Round
Use rounded joins.
@ Miter
Use mitered joins.
RenderUnit
Rendering size units.
@ Percentage
Percentage of another measurement (e.g., canvas size, feature size)
@ Millimeters
Millimeters.
@ Points
Points (e.g., for font sizes)
@ Unknown
Mixed or unknown units.
@ MetersInMapUnits
Meters value as Map units.
EndCapStyle
End cap styles for buffers.
@ Flat
Flat cap (in line with start/end of line)
@ Square
Square cap (extends past start/end of line by buffer distance)
@ RenderSymbolPreview
The render is for a symbol preview only and map based properties may not be available,...
@ Antialiasing
Use antialiasing while drawing.
@ HighQualityImageTransforms
Enable high quality image transformations, which results in better appearance of scaled or rotated ra...
VertexMarkerType
Editing vertex markers, used for showing vertices during a edit operation.
@ SemiTransparentCircle
Semi-transparent circle marker.
QFlags< SymbolRenderHint > SymbolRenderHints
Symbol render hints.
QFlags< SymbolFlag > SymbolFlags
Symbol flags.
@ RendererShouldUseSymbolLevels
If present, indicates that a QgsFeatureRenderer using the symbol should use symbol levels for best re...
@ MultiPolygon
MultiPolygon.
@ MultiLineString
MultiLineString.
SymbolCoordinateReference
Symbol coordinate reference modes.
@ Feature
Relative to feature/shape being rendered.
@ Viewport
Relative to the whole viewport/output device.
Abstract base class for all geometries.
vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry.
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
const_part_iterator const_parts_end() const
Returns STL-style iterator pointing to the imaginary const part after the last part of the geometry.
vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
const_part_iterator const_parts_begin() const
Returns STL-style iterator pointing to the const first part of the geometry.
virtual bool readXml(const QDomElement &collectionElem, const QgsPropertiesDefinition &definitions)
Reads property collection state from an XML element.
virtual bool writeXml(QDomElement &collectionElem, const QgsPropertiesDefinition &definitions) const
Writes the current state of the property collection into an XML element.
Animated marker symbol layer class.
static QgsPaintEffectRegistry * paintEffectRegistry()
Returns the application's paint effect registry, used for managing paint effects.
static QgsSymbolLayerRegistry * symbolLayerRegistry()
Returns the application's symbol layer registry, used for managing symbol layers.
static QStringList svgPaths()
Returns the paths to svg directories.
HeadType
Possible head types.
ArrowType
Possible arrow types.
static QString typeString()
Returns the string identifier for QgsColorBrewerColorRamp.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Returns a new QgsColorBrewerColorRamp color ramp created using the properties encoded in a string map...
Abstract base class for color ramps.
virtual QColor color(double value) const =0
Returns the color corresponding to a specified value.
virtual QVariantMap properties() const =0
Returns a string map containing all the color ramp's properties.
virtual QString type() const =0
Returns a string representing the color ramp type.
static QColor colorFromString(const QString &string)
Decodes a string into a color value.
static QString colorToString(const QColor &color)
Encodes a color into a string value.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates the symbol layer.
static QString typeString()
Returns the string identifier for QgsCptCityColorRamp.
Curve polygon geometry type.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
Abstract base class for curved geometry type.
virtual QgsLineString * curveToLine(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const =0
Returns a new line string geometry corresponding to a segmentized approximation of the curve.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
bool hasFeature() const
Returns true if the context has a feature associated with it.
An expression node which takes its value from a feature's field.
Abstract base class for all nodes that can appear in an expression.
virtual QgsExpressionNode::NodeType nodeType() const =0
Gets the type of this node.
Handles parsing and evaluation of expressions (formerly called "search strings").
QString expression() const
Returns the original, unmodified expression string.
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
QString parserErrorString() const
Returns parser error.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
const QgsExpressionNode * rootNode() const
Returns the root node of the expression.
Abstract base class for all 2D vector feature renderers.
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
Abstract base class for fill symbol layers.
static void pointOnLineWithDistance(double x1, double y1, double x2, double y2, double distance, double &x, double &y, double *z1=nullptr, double *z2=nullptr, double *z=nullptr, double *m1=nullptr, double *m2=nullptr, double *m=nullptr)
Calculates the point a specified distance from (x1, y1) toward a second point (x2,...
static double normalizedAngle(double angle)
Ensures that an angle is in the range 0 <= angle < 2 pi.
A geometry is the spatial representation of a feature.
QgsMultiPolygonXY asMultiPolygon() const
Returns the contents of the geometry as a multi-polygon.
QgsGeometry offsetCurve(double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit) const
Returns an offset line at a given distance and side from an input line.
QgsGeometry pointOnSurface() const
Returns a point guaranteed to lie on the surface of a geometry.
static QgsGeometry fromPolylineXY(const QgsPolylineXY &polyline)
Creates a new LineString geometry from a list of QgsPointXY points.
QgsPolygonXY asPolygon() const
Returns the contents of the geometry as a polygon.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsPolylineXY asPolyline() const
Returns the contents of the geometry as a polyline.
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
Qgis::GeometryOperationResult addRing(const QVector< QgsPointXY > &ring)
Adds a new ring to this geometry.
QgsMultiPolylineXY asMultiPolyline() const
Returns the contents of the geometry as a multi-linestring.
static QgsGeometry fromPolygonXY(const QgsPolygonXY &polygon)
Creates a new geometry from a QgsPolygonXY.
QgsGeometry buffer(double distance, int segments) const
Returns a buffer region around this geometry having the given width and with a specified number of se...
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsColorRamp from a map of properties.
static QString typeString()
Returns the string identifier for QgsGradientColorRamp.
Represents a patch shape for use in map legends.
static QString typeString()
Returns the string identifier for QgsLimitedRandomColorRamp.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Returns a new QgsLimitedRandomColorRamp color ramp created using the properties encoded in a string m...
Line string geometry type, with support for z-dimension and m-values.
const double * yData() const
Returns a const pointer to the y vertex data.
const double * xData() const
Returns a const pointer to the x vertex data.
int numPoints() const override
Returns the number of points in the curve.
Abstract base class for line symbol layers.
const QgsMapUnitScale & widthMapUnitScale() const
@ AllRings
Render both exterior and interior rings.
RenderRingFilter ringFilter() const
Returns the line symbol layer's ring filter, which controls which rings are rendered when the line sy...
virtual double width() const
Returns the estimated width for the line symbol layer.
double offset() const
Returns the line's offset.
Qgis::RenderUnit widthUnit() const
Returns the units for the line's width.
A line symbol type, for rendering LineString and MultiLineString geometries.
void setWidthUnit(Qgis::RenderUnit unit) const
Sets the width units for the whole symbol (including all symbol layers).
void setWidth(double width) const
Sets the width for the whole line symbol.
double width() const
Returns the estimated width for the whole symbol, which is the maximum width of all marker symbol lay...
Base class for all map layer types.
Struct for storing maximum and minimum scales for measurements in map units.
bool minSizeMMEnabled
Whether the minimum size in mm should be respected.
double maxScale
The maximum scale, or 0.0 if unset.
double minScale
The minimum scale, or 0.0 if unset.
double maxSizeMM
The maximum size in millimeters, or 0.0 if unset.
bool maxSizeMMEnabled
Whether the maximum size in mm should be respected.
double minSizeMM
The minimum size in millimeters, or 0.0 if unset.
A marker symbol type, for rendering Point and MultiPoint geometries.
void setSize(double size) const
Sets the size for the whole symbol.
double size() const
Returns the estimated size for the whole symbol, which is the maximum size of all marker symbol layer...
void setSizeUnit(Qgis::RenderUnit unit) const
Sets the size units for the whole symbol (including all symbol layers).
Special symbol layer that uses its sub symbol as a selective mask.
static QDomElement elseFilterExpression(QDomDocument &doc)
Creates an ElseFilter from doc.
static QDomElement expressionToOgcExpression(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr, bool requiresFilterElement=false)
Creates an OGC expression XML element from the exp expression with default values for the geometry na...
static QDomElement expressionToOgcFilter(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr)
Creates OGC filter XML element.
static QgsExpression * expressionFromOgcFilter(const QDomElement &element, QgsVectorLayer *layer=nullptr)
Parse XML with OGC filter into QGIS expression.
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
virtual bool saveProperties(QDomDocument &doc, QDomElement &element) const
Saves the current state of the effect to a DOM element.
Resolves relative paths into absolute paths and vice versa.
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
void setX(double x)
Sets the x value of the point.
static QString typeString()
Returns the string identifier for QgsPresetSchemeColorRamp.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Returns a new QgsPresetSchemeColorRamp color ramp created using the properties encoded in a string ma...
A grouped map of multiple QgsProperty objects, each referenced by an integer key value.
QSet< int > propertyKeys() const final
Returns a list of property keys contained within the collection.
QgsProperty property(int key) const final
Returns a matching property from the collection, if one exists.
A store for object properties.
bool isProjectColor() const
Returns true if the property is set to a linked project color.
bool isActive() const
Returns whether the property is currently active.
void setActive(bool active)
Sets whether the property is currently active.
A container for the context for various read/write operations on objects.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
A rectangle specified with double values.
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.
void setDevicePixelRatio(float ratio)
Sets the device pixel ratio.
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
QgsExpressionContext & expressionContext()
Gets the expression context.
void setRasterizedRenderingPolicy(Qgis::RasterizedRenderingPolicy policy)
Sets the policy controlling when rasterisation of content during renders is permitted.
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
QVector< QgsGeometry > symbolLayerClipGeometries(const QString &symbolLayerId) const
Returns clipping geometries to be applied to the symbolLayer before rendering.
static QgsRenderContext fromQPainter(QPainter *painter)
Creates a default render context given a pixel based QPainter destination.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
A fill symbol layer which fills polygons with a repeated SVG file.
Stores properties relating to a screen.
double devicePixelRatio() const
Returns the ratio between physical pixels and device-independent pixels for the screen.
bool isValid() const
Returns true if the properties are valid.
void updateRenderContextForScreen(QgsRenderContext &context) const
Updates the settings in a render context to match the screen settings.
Renders polygons using a single fill and stroke color.
void setStrokeWidthMapUnitScale(const QgsMapUnitScale &scale)
void setStrokeWidthUnit(Qgis::RenderUnit unit)
Sets the units for the width of the fill's stroke.
void setPenJoinStyle(Qt::PenJoinStyle style)
void setStrokeWidth(double strokeWidth)
void setStrokeStyle(Qt::PenStyle strokeStyle)
void setStrokeColor(const QColor &strokeColor) override
Sets the stroke color for the symbol layer.
A simple line symbol layer, which renders lines using a line in a variety of styles (e....
bool tweakDashPatternOnCorners() const
Returns true if dash patterns tweaks should be applied on sharp corners, to ensure that a double-leng...
Qt::PenJoinStyle penJoinStyle() const
Returns the pen join style used to render the line (e.g.
double trimDistanceStart() const
Returns the trim distance for the start of the line, which dictates a length from the start of the li...
double trimDistanceEnd() const
Returns the trim distance for the end of the line, which dictates a length from the end of the line a...
bool useCustomDashPattern() const
Returns true if the line uses a custom dash pattern.
Qt::PenStyle penStyle() const
Returns the pen style used to render the line (e.g.
double dashPatternOffset() const
Returns the dash pattern offset, which dictates how far along the dash pattern the pattern should sta...
bool drawInsidePolygon() const
Returns true if the line should only be drawn inside polygons, and any portion of the line which fall...
bool alignDashPattern() const
Returns true if dash patterns should be aligned to the start and end of lines, by applying subtle twe...
Holds SLD export options and other information related to SLD export of a QGIS layer style.
void pushWarning(const QString &warning)
Pushes a warning message generated during the conversion.
void pushError(const QString &error)
Pushes a error message generated during the conversion.
virtual QgsStyle::StyleEntity type() const =0
Returns the type of style entity.
An interface for classes which can visit style entity (e.g.
@ SymbolRule
Rule based symbology or label child rule.
A symbol entity for QgsStyle databases.
bool isAnimated() const
Returns true if the symbol is animated.
double frameRate() const
Returns the symbol animation frame rate (in frames per second).
Contains settings relating to symbol buffers, which draw a "halo" effect around the symbol.
We may need stable references to symbol layers, when pointers to symbol layers are not usable (when a...
std::unique_ptr< QgsSymbolLayer > createSymbolLayerFromSld(const QString &name, QDomElement &element) const
create a new instance of symbol layer given symbol layer name and SLD
void resolvePaths(const QString &name, QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving) const
Resolve paths in properties of a particular symbol layer.
void resolveFonts(const QString &name, QVariantMap &properties, const QgsReadWriteContext &context) const
Resolve fonts from the properties of a particular symbol layer.
std::unique_ptr< QgsSymbolLayer > createSymbolLayer(const QString &name, const QVariantMap &properties=QVariantMap()) const
create a new instance of symbol layer given symbol layer name and properties
static bool externalMarkerFromSld(QDomElement &element, QString &path, QString &format, int &markIndex, QColor &color, double &size)
static QColor parseColor(const QString &colorStr, bool strictEval=false)
Attempts to parse a string as a color using a variety of common formats, including hex codes,...
static bool rotationFromSldElement(QDomElement &element, QString &rotationFunc)
static void createAnchorPointElement(QDomDocument &doc, QDomElement &element, QPointF anchor)
Creates a SE 1.1 anchor point element as a child of the specified element.
static void sortVariantList(QList< QVariant > &list, Qt::SortOrder order)
Sorts the passed list in requested order.
static Qgis::MarkerClipMode decodeMarkerClipMode(const QString &string, bool *ok=nullptr)
Decodes a string representing a marker clip mode.
static QPicture symbolLayerPreviewPicture(const QgsSymbolLayer *layer, Qgis::RenderUnit units, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::SymbolType parentSymbolType=Qgis::SymbolType::Hybrid)
Draws a symbol layer preview to a QPicture.
static bool hasExternalGraphic(QDomElement &element)
Checks if element contains an ExternalGraphic element with format "image/svg+xml".
static QString encodePenStyle(Qt::PenStyle style)
static bool needMarkerLine(QDomElement &element)
static QVector< qreal > decodeSldRealVector(const QString &s)
static bool needLinePatternFill(QDomElement &element)
static std::unique_ptr< QgsSymbol > symbolFromMimeData(const QMimeData *data)
Attempts to parse mime data as a symbol.
static void clearSymbolLayerIds(QgsSymbol *symbol)
Remove recursively unique id from all symbol symbol layers and set an empty string instead.
static QString encodeSldBrushStyle(Qt::BrushStyle style)
static Qt::PenJoinStyle decodePenJoinStyle(const QString &str)
static QgsArrowSymbolLayer::HeadType decodeArrowHeadType(const QVariant &value, bool *ok=nullptr)
Decodes a value representing an arrow head type.
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
static Q_DECL_DEPRECATED QSet< const QgsSymbolLayer * > toSymbolLayerPointers(const QgsFeatureRenderer *renderer, const QSet< QgsSymbolLayerId > &symbolLayerIds)
Converts a set of symbol layer id to a set of pointers to actual symbol layers carried by the feature...
static QVariant colorRampToVariant(const QString &name, QgsColorRamp *ramp)
Saves a color ramp to a QVariantMap, wrapped in a QVariant.
static void applyScaleDependency(QDomDocument &doc, QDomElement &ruleElem, QVariantMap &props)
Checks if the properties contain scaleMinDenom and scaleMaxDenom, if available, they are added into t...
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 void drawVertexMarker(double x, double y, QPainter &p, Qgis::VertexMarkerType type, int markerSize)
Draws a vertex symbol at (painter) coordinates x, y.
static Q_DECL_DEPRECATED bool createExpressionElement(QDomDocument &doc, QDomElement &element, const QString &function)
Creates a OGC Expression element based on the provided function expression.
static bool displacementFromSldElement(QDomElement &element, QPointF &offset)
static bool hasWellKnownMark(QDomElement &element)
static std::unique_ptr< QgsColorRamp > loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
static QString getSvgParametricPath(const QString &basePath, const QColor &fillColor, const QColor &strokeColor, double strokeWidth)
Encodes a reference to a parametric SVG into a path with parameters according to the SVG Parameters s...
static Q_DECL_DEPRECATED bool createFunctionElement(QDomDocument &doc, QDomElement &element, const QString &function)
Creates an OGC function element.
static QColor decodeColor(const QString &str)
static std::unique_ptr< QgsSymbolLayer > loadSymbolLayer(QDomElement &element, const QgsReadWriteContext &context)
Reads and returns symbol layer from XML. Caller is responsible for deleting the returned object.
static bool onlineResourceFromSldElement(QDomElement &element, QString &path, QString &format)
static QPointF polygonCentroid(const QPolygonF &points)
Calculate the centroid point of a QPolygonF.
static QIcon colorRampPreviewIcon(QgsColorRamp *ramp, QSize size, int padding=0)
Returns an icon preview for a color ramp.
static QString encodeBrushStyle(Qt::BrushStyle style)
static QString svgSymbolPathToName(const QString &path, const QgsPathResolver &pathResolver)
Determines an SVG symbol's name from its path.
static bool needRasterMarker(const QDomElement &element)
Checks if element contains an ExternalGraphic element that should translate to a raster marker.
static QPixmap colorRampPreviewPixmap(QgsColorRamp *ramp, QSize size, int padding=0, Qt::Orientation direction=Qt::Horizontal, bool flipDirection=false, bool drawTransparentBackground=true)
Returns a pixmap preview for a color ramp.
static QString encodeSldAlpha(int alpha)
static void externalGraphicToSld(QDomDocument &doc, QDomElement &element, const QString &path, const QString &mime, const QColor &color, double size=-1)
static QPointF polygonPointOnSurface(const QPolygonF &points, const QVector< QPolygonF > *rings=nullptr)
Calculate a point on the surface of a QPolygonF.
static void blurImageInPlace(QImage &image, QRect rect, int radius, bool alphaOnly)
Blurs an image in place, e.g. creating Qt-independent drop shadows.
static QList< double > prettyBreaks(double minimum, double maximum, int classes)
Computes a sequence of about 'classes' equally spaced round values which cover the range of values fr...
static QPointF toPoint(const QVariant &value, bool *ok=nullptr)
Converts a value to a point.
static void premultiplyColor(QColor &rgb, int alpha)
Converts a QColor into a premultiplied ARGB QColor value using a specified alpha value.
static void saveProperties(QVariantMap props, QDomDocument &doc, QDomElement &element)
Saves the map of properties to XML.
static void multiplyImageOpacity(QImage *image, qreal opacity)
Multiplies opacity of image pixel values with a (global) transparency value.
static bool functionFromSldElement(QDomElement &element, QString &function)
static bool saveColorsToGpl(QFile &file, const QString &paletteName, const QgsNamedColorList &colors)
Exports colors to a gpl GIMP palette file.
static std::unique_ptr< QgsSymbolLayer > createFillLayerFromSld(QDomElement &element)
Creates a new fill layer from a SLD DOM element.
static QColor parseColorWithAlpha(const QString &colorStr, bool &containsAlpha, bool strictEval=false)
Attempts to parse a string as a color using a variety of common formats, including hex codes,...
static bool hasSldSymbolizer(const QDomElement &element)
Returns true if a DOM element contains an SLD Symbolizer element.
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
static QSizeF toSize(const QVariant &value, bool *ok=nullptr)
Converts a value to a size.
static double rescaleUom(double size, Qgis::RenderUnit unit, const QVariantMap &props)
Rescales the given size based on the uomScale found in the props, if any is found,...
static bool needEllipseMarker(QDomElement &element)
static std::unique_ptr< QgsSymbolLayer > createMarkerLayerFromSld(QDomElement &element)
Creates a new marker layer from a SLD DOM element.
static QgsNamedColorList colorListFromMimeData(const QMimeData *data)
Attempts to parse mime data as a list of named colors.
static void clearSymbolLayerMasks(QgsSymbol *symbol)
Remove recursively masks from all symbol symbol layers.
static bool isSharpCorner(QPointF p1, QPointF p2, QPointF p3)
Returns true if the angle formed by the line p1 - p2 - p3 forms a "sharp" corner.
static QString ogrFeatureStylePen(double width, double mmScaleFactor, double mapUnitsScaleFactor, const QColor &c, Qt::PenJoinStyle joinStyle=Qt::MiterJoin, Qt::PenCapStyle capStyle=Qt::FlatCap, double offset=0.0, const QVector< qreal > *dashPattern=nullptr)
Create ogr feature style string for pen.
static Qt::PenCapStyle decodePenCapStyle(const QString &str)
static double rendererFrameRate(const QgsFeatureRenderer *renderer)
Calculates the frame rate (in frames per second) at which the given renderer must be redrawn.
static QgsStringMap getSvgParameterList(QDomElement &element)
static bool needSvgFill(QDomElement &element)
static bool createSymbolLayerListFromSld(QDomElement &element, Qgis::GeometryType geomType, QList< QgsSymbolLayer * > &layers)
Creates a symbol layer list from a DOM element.
static bool externalGraphicFromSld(QDomElement &element, QString &path, QString &mime, QColor &color, double &size)
static Q_DECL_DEPRECATED 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 QIcon symbolLayerPreviewIcon(const QgsSymbolLayer *layer, Qgis::RenderUnit u, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::SymbolType parentSymbolType=Qgis::SymbolType::Hybrid, QgsMapLayer *mapLayer=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Draws a symbol layer preview to an icon.
static QString encodeSldLineCapStyle(Qt::PenCapStyle style)
static QString encodeSldUom(Qgis::RenderUnit unit, double *scaleFactor)
Encodes a render unit into an SLD unit of measure string.
static QList< QList< QPolygonF > > toQPolygonF(const QgsGeometry &geometry, Qgis::SymbolType type)
Converts a geometry to a set of QPolygonF objects representing how the geometry should be drawn for a...
static std::unique_ptr< QgsSymbol > loadSymbol(const QDomElement &element, const QgsReadWriteContext &context)
Attempts to load a symbol from a DOM element.
static QVector< qreal > decodeRealVector(const QString &s)
static bool lineFromSld(QDomElement &element, Qt::PenStyle &penStyle, QColor &color, double &width, Qt::PenJoinStyle *penJoinStyle=nullptr, Qt::PenCapStyle *penCapStyle=nullptr, QVector< qreal > *customDashPattern=nullptr, double *dashOffset=nullptr)
static QPainter::CompositionMode decodeBlendMode(const QString &s)
static Qgis::ScaleMethod decodeScaleMethod(const QString &str)
Decodes a symbol scale method from a string.
static Q_DECL_DEPRECATED void createOpacityElement(QDomDocument &doc, QDomElement &element, const QString &alphaFunc)
Creates SLD opacity element.
static std::unique_ptr< QgsSymbolLayer > createLineLayerFromSld(QDomElement &element)
Creates a new line layer from a SLD DOM element.
static QString ogrFeatureStyleBrush(const QColor &fillColr)
Create ogr feature style string for brush.
static bool pointInPolygon(const QPolygonF &points, QPointF point)
Calculate whether a point is within of a QPolygonF.
static QStringList listSvgFiles()
Returns a list of all available svg files.
static QString encodeLineClipMode(Qgis::LineClipMode mode)
Encodes a line clip mode to a string.
static QPixmap symbolPreviewPixmap(const QgsSymbol *symbol, QSize size, int padding=0, QgsRenderContext *customContext=nullptr, bool selected=false, const QgsExpressionContext *expressionContext=nullptr, const QgsLegendPatchShape *shape=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Returns a pixmap preview for a color ramp.
static bool convertPolygonSymbolizerToPointMarker(QDomElement &element, QList< QgsSymbolLayer * > &layerList)
Converts a polygon symbolizer element to a list of marker symbol layers.
static Qgis::LineClipMode decodeLineClipMode(const QString &string, bool *ok=nullptr)
Decodes a string representing a line clip mode.
static bool needSvgMarker(const QDomElement &element)
Checks if element contains an ExternalGraphic element that should translate to an SVG marker.
static QStringList listSvgFilesAt(const QString &directory)
Returns a list of svg files at the specified directory.
static bool needFontMarker(QDomElement &element)
static QString encodePenCapStyle(Qt::PenCapStyle style)
static QPointF pointOnLineWithDistance(QPointF startPoint, QPointF directionPoint, double distance)
Returns a point on the line from startPoint to directionPoint that is a certain distance away from th...
static QFont::Style decodeSldFontStyle(const QString &str)
static QSize tileSize(int width, int height, double &angleRad)
Calculate the minimum size in pixels of a symbol tile given the symbol width and height and the symbo...
static QString fieldOrExpressionFromExpression(QgsExpression *expression)
Returns a field name if the whole expression is just a name of the field .
static bool opacityFromSldElement(QDomElement &element, QString &alphaFunc)
static QString encodeSldFontWeight(int weight)
static Q_DECL_DEPRECATED void externalMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &path, const QString &format, int *markIndex=nullptr, const QColor &color=QColor(), double size=-1)
Exports a marker to an SLD definition.
static QMimeData * colorListToMimeData(const QgsNamedColorList &colorList, bool allFormats=true)
Creates mime data from a list of named colors.
static Qt::BrushStyle decodeBrushStyle(const QString &str)
static QVector< QgsGeometry > collectSymbolLayerClipGeometries(const QgsRenderContext &context, const QString &symbolLayerId, const QRectF &bounds)
Returns a list of the symbol layer clip geometries to be used for the symbol layer with the specified...
static Qt::PenCapStyle decodeSldLineCapStyle(const QString &str)
static QgsNamedColorList importColorsFromGpl(QFile &file, bool &ok, QString &name)
Imports colors from a gpl GIMP palette file.
static QString encodeSize(QSizeF size)
Encodes a QSizeF to a string.
static QDomElement createVendorOptionElement(QDomDocument &doc, const QString &name, const QString &value)
static double sizeInPixelsFromSldUom(const QString &uom, double size)
Returns the size scaled in pixels according to the uom attribute.
static void appendPolyline(QPolygonF &target, const QPolygonF &line)
Appends a polyline line to an existing target polyline.
static bool wellKnownMarkerFromSld(QDomElement &element, QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle, double &strokeWidth, double &size)
Extracts properties from an SLD marker definition.
static void mergeScaleDependencies(double mScaleMinDenom, double mScaleMaxDenom, QVariantMap &props)
Merges the local scale limits, if any, with the ones already in the map, if any.
static QgsSymbol * restrictedSizeSymbol(const QgsSymbol *s, double minSize, double maxSize, QgsRenderContext *context, double &width, double &height, bool *ok=nullptr)
Creates a new symbol with size restricted to min/max size if original size is out of min/max range.
static QString colorToName(const QColor &color)
Returns a friendly display name for a color.
static int decodeSldAlpha(const QString &str)
static QString encodeSldLineJoinStyle(Qt::PenJoinStyle style)
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 void drawStippledBackground(QPainter *painter, QRect rect)
static QList< QColor > parseColorList(const QString &colorStr)
Attempts to parse a string as a list of colors using a variety of common formats, including hex codes...
static QString encodeColor(const QColor &color)
static Qt::PenJoinStyle decodeSldLineJoinStyle(const QString &str)
static QVariantMap parseProperties(const QDomElement &element)
Parses the properties from XML and returns a map.
static bool fillFromSld(QDomElement &element, Qt::BrushStyle &brushStyle, QColor &color)
static Qgis::EndCapStyle penCapStyleToEndCapStyle(Qt::PenCapStyle style)
Converts a Qt pen cap style to a QGIS end cap style.
static QMimeData * symbolToMimeData(const QgsSymbol *symbol)
Creates new mime data from a symbol.
static QString encodeSldFontStyle(QFont::Style style)
static QColor colorFromMimeData(const QMimeData *data, bool &hasAlpha)
Attempts to parse mime data as a color.
static int decodeSldFontWeight(const QString &str)
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
static Q_DECL_DEPRECATED void fillToSld(QDomDocument &doc, QDomElement &element, Qt::BrushStyle brushStyle, const QColor &color=QColor())
Exports fill details to an SLD element.
static double polylineLength(const QPolygonF &polyline)
Returns the total length of a polyline.
static QDomElement saveColorRamp(const QString &name, const QgsColorRamp *ramp, QDomDocument &doc)
Encodes a color ramp's settings to an XML element.
static Qgis::RenderUnit decodeSldUom(const QString &str, double *scaleFactor=nullptr)
Decodes a SLD unit of measure string to a render unit.
static Q_DECL_DEPRECATED void createGeometryElement(QDomDocument &doc, QDomElement &element, const QString &geomFunc)
Creates an SLD geometry element.
static QgsArrowSymbolLayer::ArrowType decodeArrowType(const QVariant &value, bool *ok=nullptr)
Decodes a value representing an arrow type.
static void clearSymbolMap(QgsSymbolMap &symbols)
static Qt::BrushStyle decodeSldBrushStyle(const QString &str)
static void resetSymbolLayerIds(QgsSymbol *symbol)
Regenerate recursively unique id from all symbol symbol layers.
static double estimateMaxSymbolBleed(QgsSymbol *symbol, const QgsRenderContext &context)
Returns the maximum estimated bleed for the symbol.
static Q_DECL_DEPRECATED void wellKnownMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &name, const QColor &color, const QColor &strokeColor, Qt::PenStyle strokeStyle, double strokeWidth=-1, double size=-1)
Exports a marker to SLD.
static QString symbolProperties(QgsSymbol *symbol)
Returns a string representing the symbol.
static bool geometryFromSldElement(QDomElement &element, QString &geomFunc)
static QString encodeScaleMethod(Qgis::ScaleMethod scaleMethod)
Encodes a symbol scale method to a string.
static void createOnlineResourceElement(QDomDocument &doc, QDomElement &element, const QString &path, const QString &format)
static Qt::PenStyle decodePenStyle(const QString &str)
static Q_DECL_DEPRECATED void createRotationElement(QDomDocument &doc, QDomElement &element, const QString &rotationFunc)
Creates SLD rotation element.
static Qgis::SymbolCoordinateReference decodeCoordinateReference(const QString &string, bool *ok=nullptr)
Decodes a string representing a symbol coordinate reference mode.
static QgsSymbolMap loadSymbols(QDomElement &element, const QgsReadWriteContext &context)
Reads a collection of symbols from XML and returns them in a map. Caller is responsible for deleting ...
static QString encodePoint(QPointF point)
Encodes a QPointF to a string.
static Q_DECL_DEPRECATED void labelTextToSld(QDomDocument &doc, QDomElement &element, const QString &label, const QFont &font, const QColor &color=QColor(), double size=-1)
Exports label text to SLD.
static QDomElement saveSymbols(QgsSymbolMap &symbols, const QString &tagName, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a collection of symbols to XML with specified tagName for the top-level element.
static std::unique_ptr< QgsExpression > fieldOrExpressionToExpression(const QString &fieldOrExpression)
Returns a new valid expression instance for given field or expression string.
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
static QgsStringMap getVendorOptionList(QDomElement &element)
static Qgis::JoinStyle penJoinStyleToJoinStyle(Qt::PenJoinStyle style)
Converts a Qt pen joinstyle to a QGIS join style.
static QIcon symbolPreviewIcon(const QgsSymbol *symbol, QSize size, int padding=0, QgsLegendPatchShape *shape=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Returns an icon preview for a color ramp.
static QMimeData * colorToMimeData(const QColor &color)
Creates mime data from a color.
static bool condenseFillAndOutline(QgsFillSymbolLayer *fill, QgsLineSymbolLayer *outline)
Attempts to condense a fill and outline layer, by moving the outline layer to the fill symbol's strok...
static QPointF decodePoint(const QString &string)
Decodes a QSizeF from a string.
static QPolygonF polylineSubstring(const QPolygonF &polyline, double startOffset, double endOffset)
Returns the substring of a polyline which starts at startOffset from the beginning of the line and en...
static bool needPointPatternFill(QDomElement &element)
static QString encodeSldRealVector(const QVector< qreal > &v)
static QString encodeCoordinateReference(Qgis::SymbolCoordinateReference coordinateReference)
Encodes a symbol coordinate reference mode to a string.
static bool needRasterImageFill(QDomElement &element)
Checks if element contains a graphic fill with a raster image of type PNG, JPEG or GIF.
static QDomElement createSvgParameterElement(QDomDocument &doc, const QString &name, const QString &value)
static QString encodeMarkerClipMode(Qgis::MarkerClipMode mode)
Encodes a marker clip mode to a string.
static void lineToSld(QDomDocument &doc, QDomElement &element, Qt::PenStyle penStyle, const QColor &color, QgsSldExportContext &context, double width=-1, const Qt::PenJoinStyle *penJoinStyle=nullptr, const Qt::PenCapStyle *penCapStyle=nullptr, const QVector< qreal > *customDashPattern=nullptr, double dashOffset=0.0)
static QSizeF decodeSize(const QString &string)
Decodes a QSizeF from a string.
static bool hasExternalGraphicV2(const QDomElement &element, const QString format=QString())
Checks if element contains an ExternalGraphic element, if the optional format is specified it will al...
static QString encodeRealVector(const QVector< qreal > &v)
Abstract base class for symbol layers.
virtual QgsSymbolLayer * clone() const =0
Shall be reimplemented by subclasses to create a deep copy of the instance.
virtual bool setSubSymbol(QgsSymbol *symbol)
Sets layer's subsymbol. takes ownership of the passed symbol.
void setId(const QString &id)
Set symbol layer identifier This id has to be unique in the whole project.
bool isLocked() const
Returns true if the symbol layer colors are locked and the layer will ignore any symbol-level color c...
Property
Data definable properties.
virtual double estimateMaxBleed(const QgsRenderContext &context) const
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the layer.
virtual QVariantMap properties() const =0
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
bool enabled() const
Returns true if symbol layer is enabled and will be drawn.
virtual QString layerType() const =0
Returns a string that represents this layer type.
int renderingPass() const
Specifies the rendering pass in which this symbol layer should be rendered.
QString id() const
Returns symbol layer identifier This id is unique in the whole project.
virtual QgsSymbol * subSymbol()
Returns the symbol's sub symbol, if present.
Qgis::SymbolLayerUserFlags userFlags() const
Returns user-controlled flags which control the symbol layer's behavior.
virtual QColor color() const
Returns the "representative" color of the symbol layer.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol layer property definitions.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
virtual bool hasDataDefinedProperties() const
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
Encapsulates the context in which a symbol is being rendered.
void setOriginalGeometryType(Qgis::GeometryType type)
Sets the geometry type for the original feature geometry being rendered.
Abstract base class for all rendered symbols.
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol's property collection, used for data defined overrides.
QgsSymbolAnimationSettings & animationSettings()
Returns a reference to the symbol animation settings.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol property definitions.
Qgis::SymbolFlags flags() const
Returns flags for the symbol.
qreal opacity() const
Returns the opacity for the symbol.
bool clipFeaturesToExtent() const
Returns whether features drawn by the symbol will be clipped to the render context's extent.
QgsSymbolBufferSettings * bufferSettings()
Returns the symbol buffer settings, which control an optional "halo" effect around the symbol.
bool hasDataDefinedProperties() const
Returns whether the symbol utilizes any data defined properties.
QgsSymbolLayerList symbolLayers() const
Returns the list of symbol layers contained in the symbol.
Qgis::RenderUnit extentBufferSizeUnit() const
Returns the units for the buffer size.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
QColor color() const
Returns the symbol's color.
Qgis::SymbolType type() const
Returns the symbol's type.
double extentBuffer() const
Returns the symbol's extent buffer.
bool forceRHR() const
Returns true if polygon features drawn by the symbol will be reoriented to follow the standard right-...
static Q_INVOKABLE Qgis::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
static Qgis::GeometryType geometryType(Qgis::WkbType type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement.
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement.
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 qgsVariantLessThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is less than the second.
bool qgsVariantGreaterThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is greater than the second.
#define Q_NOWARN_DEPRECATED_POP
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
QString qgsFlagValueToKeys(const T &value, bool *returnOk=nullptr)
Returns the value for the given keys of a flag.
T qgsFlagKeysToValue(const QString &keys, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given keys of a flag.
#define Q_NOWARN_DEPRECATED_PUSH
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QVector< QgsPolylineXY > QgsPolygonXY
Polygon: first item of the list is outer ring, inner rings (if any) start from second item.
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)
QList< QgsSymbolLayer * > QgsSymbolLayerList
QList< QPolygonF > offsetLine(QPolygonF polyline, double dist, Qgis::GeometryType geometryType)
calculate geometry shifted by a specified distance
QPolygonF lineStringToQPolygonF(const QgsLineString *line)
QPolygonF curveToPolygonF(const QgsCurve *curve)
void changeSymbolLayerIds(QgsSymbolLayer *sl, Functor &&generateId)
QList< QPair< QColor, QString > > QgsNamedColorList
QMap< QString, QgsSymbol * > QgsSymbolMap
QMap< QString, QString > QgsStringMap
Contains information relating to a node (i.e.
QString identifier
A string identifying the node.
QgsStyleEntityVisitorInterface::NodeType type
Node type.
Contains information relating to the style entity currently being visited.
const QgsStyleEntityInterface * entity
Reference to style entity being visited.
QString identifier
A string identifying the style entity.