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;
1804 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1805 if ( graphicElem.isNull() )
1808 const QDomElement externalGraphicElem = graphicElem.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
1809 if ( externalGraphicElem.isNull() )
1813 const QDomElement formatElem = externalGraphicElem.firstChildElement( QStringLiteral(
"Format" ) );
1814 if ( formatElem.isNull() )
1817 const QString elementFormat = formatElem.firstChild().nodeValue();
1818 if ( ! format.isEmpty() && elementFormat != format )
1820 QgsDebugMsgLevel(
"unsupported External Graphic format found: " + elementFormat, 4 );
1825 const QDomElement onlineResourceElem = externalGraphicElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1826 const QDomElement inlineContentElem = externalGraphicElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1827 if ( !onlineResourceElem.isNull() )
1832 else if ( !inlineContentElem.isNull() )
1845 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1846 if ( graphicElem.isNull() )
1849 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1850 if ( markElem.isNull() )
1853 const QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
1854 return !wellKnownNameElem.isNull();
1860 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1861 if ( graphicElem.isNull() )
1864 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1865 if ( markElem.isNull() )
1869 const QDomElement formatElem = markElem.firstChildElement( QStringLiteral(
"Format" ) );
1870 if ( formatElem.isNull() )
1873 const QString format = formatElem.firstChild().nodeValue();
1874 if ( format != QLatin1String(
"ttf" ) )
1876 QgsDebugError(
"unsupported Graphic Mark format found: " + format );
1881 const QDomElement onlineResourceElem = markElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1882 const QDomElement inlineContentElem = markElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1883 if ( !onlineResourceElem.isNull() )
1886 const QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
1887 if ( !markIndexElem.isNull() )
1890 else if ( !inlineContentElem.isNull() )
1905 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1906 if ( graphicElem.isNull() )
1910 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
1912 if ( it.key() == QLatin1String(
"widthHeightFactor" ) )
1923 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1924 if ( strokeElem.isNull() )
1927 QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral(
"GraphicStroke" ) );
1928 if ( graphicStrokeElem.isNull() )
1936 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1937 if ( fillElem.isNull() )
1940 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1941 if ( graphicFillElem.isNull() )
1944 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1945 if ( graphicElem.isNull() )
1951 QColor fillColor, strokeColor;
1952 double size, strokeWidth;
1953 Qt::PenStyle strokeStyle;
1954 if ( !
wellKnownMarkerFromSld( graphicElem, name, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
1957 if ( name != QLatin1String(
"horline" ) )
1965 const double angle = angleFunc.toDouble( &ok );
1971 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1972 if ( fillElem.isNull() )
1975 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1976 if ( graphicFillElem.isNull() )
1979 const QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1980 if ( graphicElem.isNull() )
1983 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1984 if ( markElem.isNull() )
1992 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1993 if ( fillElem.isNull() )
1996 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1997 if ( graphicFillElem.isNull() )
2005 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
2006 if ( fillElem.isNull() )
2009 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
2010 if ( graphicFillElem.isNull() )
2030 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
2031 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
2035 bool validFill =
false, validStroke =
false;
2040 Qt::BrushStyle fillStyle;
2042 if (
fillFromSld( fillElem, fillStyle, fillColor ) )
2048 Qt::PenStyle strokeStyle;
2049 double strokeWidth = 1.0, dashOffset = 0.0;
2050 QVector<qreal> customDashPattern;
2052 if (
lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth,
2053 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2056 if ( validFill || validStroke )
2059 map[QStringLiteral(
"name" )] = QStringLiteral(
"square" );
2062 map[QStringLiteral(
"size" )] = QString::number( 6 );
2063 map[QStringLiteral(
"angle" )] = QString::number( 0 );
2064 map[QStringLiteral(
"offset" )] =
encodePoint( QPointF( 0, 0 ) );
2071 bool validFill =
false, validStroke =
false;
2074 QString name, format;
2076 QColor fillColor, strokeColor;
2077 double strokeWidth = 1.0, size = 0.0, angle = 0.0;
2081 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
2082 if ( !graphicFillElem.isNull() )
2085 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
2086 if ( !graphicElem.isNull() )
2092 const QDomElement graphicChildElem = graphicElem.firstChildElement();
2093 while ( !graphicChildElem.isNull() )
2095 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2098 const QDomElement wellKnownNameElem = graphicChildElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
2099 if ( !wellKnownNameElem.isNull() )
2101 name = wellKnownNameElem.firstChild().nodeValue();
2107 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) || graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2110 const QDomElement formatElem = graphicChildElem.firstChildElement( QStringLiteral(
"Format" ) );
2111 if ( formatElem.isNull() )
2114 format = formatElem.firstChild().nodeValue();
2118 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) && format != QLatin1String(
"image/svg+xml" ) )
2123 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format != QLatin1String(
"ttf" ) )
2127 const QDomElement onlineResourceElem = graphicChildElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
2128 const QDomElement inlineContentElem = graphicChildElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
2130 if ( !onlineResourceElem.isNull() )
2132 name = onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) );
2134 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format == QLatin1String(
"ttf" ) )
2137 if ( name.startsWith( QLatin1String(
"ttf://" ) ) )
2138 name = name.mid( 6 );
2141 const QDomElement markIndexElem = graphicChildElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
2142 if ( markIndexElem.isNull() )
2146 const int v = markIndexElem.firstChild().nodeValue().toInt( &ok );
2157 else if ( !inlineContentElem.isNull() )
2167 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2169 name = QStringLiteral(
"square" );
2176 if ( found && graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2183 Qt::BrushStyle markFillStyle;
2185 QDomElement markFillElem = graphicChildElem.firstChildElement( QStringLiteral(
"Fill" ) );
2186 if (
fillFromSld( markFillElem, markFillStyle, fillColor ) )
2191 Qt::PenStyle strokeStyle;
2192 double strokeWidth = 1.0, dashOffset = 0.0;
2193 QVector<qreal> customDashPattern;
2195 QDomElement markStrokeElem = graphicChildElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2196 if (
lineFromSld( markStrokeElem, strokeStyle, strokeColor, strokeWidth,
2197 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2204 const QDomElement opacityElem = graphicElem.firstChildElement( QStringLiteral(
"Opacity" ) );
2205 if ( !opacityElem.isNull() )
2206 fillColor.setAlpha(
decodeSldAlpha( opacityElem.firstChild().nodeValue() ) );
2208 const QDomElement sizeElem = graphicElem.firstChildElement( QStringLiteral(
"Size" ) );
2209 if ( !sizeElem.isNull() )
2212 const double v = sizeElem.firstChild().nodeValue().toDouble( &ok );
2221 const double v = angleFunc.toDouble( &ok );
2231 if ( validFill || validStroke )
2233 if ( format == QLatin1String(
"image/svg+xml" ) )
2236 map[QStringLiteral(
"name" )] = name;
2237 map[QStringLiteral(
"fill" )] = fillColor.name();
2238 map[QStringLiteral(
"outline" )] = strokeColor.name();
2239 map[QStringLiteral(
"outline-width" )] = QString::number( strokeWidth );
2241 map[QStringLiteral(
"size" )] = QString::number( size );
2243 map[QStringLiteral(
"angle" )] = QString::number( angle );
2244 if ( !offset.isNull() )
2245 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
2248 else if ( format == QLatin1String(
"ttf" ) )
2251 map[QStringLiteral(
"font" )] = name;
2252 map[QStringLiteral(
"chr" )] = markIndex;
2255 map[QStringLiteral(
"size" )] = QString::number( size );
2257 map[QStringLiteral(
"angle" )] = QString::number( angle );
2258 if ( !offset.isNull() )
2259 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
2265 if ( layers.isEmpty() )
2268 layerList << layers;
2276 fillToSld( doc, element, context, brushStyle, color );
2281 QString patternName;
2282 switch ( brushStyle )
2287 case Qt::SolidPattern:
2288 if ( color.isValid() )
2291 if ( color.alpha() < 255 )
2296 case Qt::CrossPattern:
2297 case Qt::DiagCrossPattern:
2298 case Qt::HorPattern:
2299 case Qt::VerPattern:
2300 case Qt::BDiagPattern:
2301 case Qt::FDiagPattern:
2302 case Qt::Dense1Pattern:
2303 case Qt::Dense2Pattern:
2304 case Qt::Dense3Pattern:
2305 case Qt::Dense4Pattern:
2306 case Qt::Dense5Pattern:
2307 case Qt::Dense6Pattern:
2308 case Qt::Dense7Pattern:
2313 context.
pushWarning( QObject::tr(
"Brush style '%1' is not supported for SLD" ).arg( brushStyle ) );
2317 QDomElement graphicFillElem = doc.createElement( QStringLiteral(
"se:GraphicFill" ) );
2318 element.appendChild( graphicFillElem );
2320 QDomElement graphicElem = doc.createElement( QStringLiteral(
"se:Graphic" ) );
2321 graphicFillElem.appendChild( graphicElem );
2323 const QColor fillColor = patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
2324 const QColor strokeColor = !patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
2327 wellKnownMarkerToSld( doc, graphicElem, patternName, fillColor, strokeColor, Qt::SolidLine, context, -1, -1 );
2334 brushStyle = Qt::SolidPattern;
2335 color = QColor( 128, 128, 128 );
2337 if ( element.isNull() )
2339 brushStyle = Qt::NoBrush;
2344 const QDomElement graphicFillElem = element.firstChildElement( QStringLiteral(
"GraphicFill" ) );
2346 if ( graphicFillElem.isNull() )
2349 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2351 QgsDebugMsgLevel( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ), 2 );
2353 if ( it.key() == QLatin1String(
"fill" ) )
2354 color = QColor( it.value() );
2355 else if ( it.key() == QLatin1String(
"fill-opacity" ) )
2361 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
2362 if ( graphicElem.isNull() )
2365 QString patternName = QStringLiteral(
"square" );
2366 QColor fillColor, strokeColor;
2367 double strokeWidth, size;
2368 Qt::PenStyle strokeStyle;
2369 if ( !
wellKnownMarkerFromSld( graphicElem, patternName, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
2373 if ( brushStyle == Qt::NoBrush )
2376 const QColor
c = patternName.startsWith( QLatin1String(
"brush://" ) ) ? fillColor : strokeColor;
2386 const Qt::PenJoinStyle *penJoinStyle,
const Qt::PenCapStyle *penCapStyle,
2387 const QVector<qreal> *customDashPattern,
double dashOffset )
2389 QVector<qreal> dashPattern;
2390 const QVector<qreal> *pattern = &dashPattern;
2392 if ( penStyle == Qt::CustomDashLine && !customDashPattern )
2394 context.
pushWarning( QObject::tr(
"WARNING: Custom dash pattern required but not provided. Using default dash pattern." ) );
2395 penStyle = Qt::DashLine;
2407 dashPattern.push_back( 4.0 );
2408 dashPattern.push_back( 2.0 );
2411 dashPattern.push_back( 1.0 );
2412 dashPattern.push_back( 2.0 );
2414 case Qt::DashDotLine:
2415 dashPattern.push_back( 4.0 );
2416 dashPattern.push_back( 2.0 );
2417 dashPattern.push_back( 1.0 );
2418 dashPattern.push_back( 2.0 );
2420 case Qt::DashDotDotLine:
2421 dashPattern.push_back( 4.0 );
2422 dashPattern.push_back( 2.0 );
2423 dashPattern.push_back( 1.0 );
2424 dashPattern.push_back( 2.0 );
2425 dashPattern.push_back( 1.0 );
2426 dashPattern.push_back( 2.0 );
2429 case Qt::CustomDashLine:
2430 Q_ASSERT( customDashPattern );
2431 pattern = customDashPattern;
2435 context.
pushWarning( QObject::tr(
"Pen style '%1' is not supported for SLD" ).arg( penStyle ) );
2439 if ( color.isValid() )
2442 if ( color.alpha() < 255 )
2449 else if ( width == 0 )
2459 if ( !pattern->isEmpty() )
2469 Qt::PenStyle &penStyle, QColor &color,
double &width,
2470 Qt::PenJoinStyle *penJoinStyle, Qt::PenCapStyle *penCapStyle,
2471 QVector<qreal> *customDashPattern,
double *dashOffset )
2475 penStyle = Qt::SolidLine;
2476 color = QColor( 0, 0, 0 );
2479 *penJoinStyle = Qt::BevelJoin;
2481 *penCapStyle = Qt::SquareCap;
2482 if ( customDashPattern )
2483 customDashPattern->clear();
2487 if ( element.isNull() )
2489 penStyle = Qt::NoPen;
2495 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2497 QgsDebugMsgLevel( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ), 2 );
2499 if ( it.key() == QLatin1String(
"stroke" ) )
2501 color = QColor( it.value() );
2503 else if ( it.key() == QLatin1String(
"stroke-opacity" ) )
2507 else if ( it.key() == QLatin1String(
"stroke-width" ) )
2510 const double w = it.value().toDouble( &ok );
2514 else if ( it.key() == QLatin1String(
"stroke-linejoin" ) && penJoinStyle )
2518 else if ( it.key() == QLatin1String(
"stroke-linecap" ) && penCapStyle )
2522 else if ( it.key() == QLatin1String(
"stroke-dasharray" ) )
2525 if ( !dashPattern.isEmpty() )
2529 bool dashPatternFound =
false;
2531 if ( dashPattern.count() == 2 )
2533 if ( dashPattern.at( 0 ) == 4.0 &&
2534 dashPattern.at( 1 ) == 2.0 )
2536 penStyle = Qt::DashLine;
2537 dashPatternFound =
true;
2539 else if ( dashPattern.at( 0 ) == 1.0 &&
2540 dashPattern.at( 1 ) == 2.0 )
2542 penStyle = Qt::DotLine;
2543 dashPatternFound =
true;
2546 else if ( dashPattern.count() == 4 )
2548 if ( dashPattern.at( 0 ) == 4.0 &&
2549 dashPattern.at( 1 ) == 2.0 &&
2550 dashPattern.at( 2 ) == 1.0 &&
2551 dashPattern.at( 3 ) == 2.0 )
2553 penStyle = Qt::DashDotLine;
2554 dashPatternFound =
true;
2557 else if ( dashPattern.count() == 6 )
2559 if ( dashPattern.at( 0 ) == 4.0 &&
2560 dashPattern.at( 1 ) == 2.0 &&
2561 dashPattern.at( 2 ) == 1.0 &&
2562 dashPattern.at( 3 ) == 2.0 &&
2563 dashPattern.at( 4 ) == 1.0 &&
2564 dashPattern.at( 5 ) == 2.0 )
2566 penStyle = Qt::DashDotDotLine;
2567 dashPatternFound =
true;
2572 if ( !dashPatternFound )
2574 if ( customDashPattern )
2576 penStyle = Qt::CustomDashLine;
2577 *customDashPattern = dashPattern;
2581 QgsDebugMsgLevel( QStringLiteral(
"custom dash pattern required but not provided. Using default dash pattern." ), 2 );
2582 penStyle = Qt::DashLine;
2587 else if ( it.key() == QLatin1String(
"stroke-dashoffset" ) && dashOffset )
2590 const double d = it.value().toDouble( &ok );
2600 const QString &path,
const QString &mime,
2601 const QColor &color,
double size )
2603 QDomElement externalGraphicElem = doc.createElement( QStringLiteral(
"se:ExternalGraphic" ) );
2604 element.appendChild( externalGraphicElem );
2613 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2615 element.appendChild( sizeElem );
2620 const QString &path,
const QColor &fillColor,
double size,
const QColor &strokeColor,
double strokeWidth )
2623 parametricSvgToSld( doc, graphicElem, path, fillColor, size, strokeColor, strokeWidth, context );
2633 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Parametric SVG" ) ) );
2634 const QString parametricPath =
getSvgParametricPath( path, fillColor, strokeColor, strokeWidth );
2637 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Plain SVG fallback, no parameters" ) ) );
2640 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Well known marker fallback" ) ) );
2646 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2648 graphicElem.appendChild( sizeElem );
2655 if ( fillColor.isValid() )
2657 url.addQueryItem( QStringLiteral(
"fill" ), fillColor.name() );
2658 url.addQueryItem( QStringLiteral(
"fill-opacity" ),
encodeSldAlpha( fillColor.alpha() ) );
2662 url.addQueryItem( QStringLiteral(
"fill" ), QStringLiteral(
"#000000" ) );
2663 url.addQueryItem( QStringLiteral(
"fill-opacity" ), QStringLiteral(
"1" ) );
2665 if ( strokeColor.isValid() )
2667 url.addQueryItem( QStringLiteral(
"outline" ), strokeColor.name() );
2668 url.addQueryItem( QStringLiteral(
"outline-opacity" ),
encodeSldAlpha( strokeColor.alpha() ) );
2672 url.addQueryItem( QStringLiteral(
"outline" ), QStringLiteral(
"#000000" ) );
2673 url.addQueryItem( QStringLiteral(
"outline-opacity" ), QStringLiteral(
"1" ) );
2675 url.addQueryItem( QStringLiteral(
"outline-width" ), QString::number( strokeWidth ) );
2676 const QString params = url.toString( QUrl::FullyEncoded );
2677 if ( params.isEmpty() )
2683 return basePath +
"?" + params;
2688 QString &path, QString &mime,
2689 QColor &color,
double &size )
2694 QDomElement externalGraphicElem = element.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
2695 if ( externalGraphicElem.isNull() )
2700 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2701 if ( !sizeElem.isNull() )
2704 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2713 const QString &path,
const QString &format,
int *markIndex,
2714 const QColor &color,
double size )
2722 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2723 element.appendChild( markElem );
2729 QDomElement markIndexElem = doc.createElement( QStringLiteral(
"se:MarkIndex" ) );
2730 markIndexElem.appendChild( doc.createTextNode( QString::number( *markIndex ) ) );
2731 markElem.appendChild( markIndexElem );
2735 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2736 fillToSld( doc, fillElem, context, Qt::SolidPattern, color );
2737 markElem.appendChild( fillElem );
2742 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2744 element.appendChild( sizeElem );
2749 QString &path, QString &format,
int &markIndex,
2750 QColor &color,
double &size )
2758 QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2759 if ( markElem.isNull() )
2764 const QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
2765 if ( !markIndexElem.isNull() )
2768 const int i = markIndexElem.firstChild().nodeValue().toInt( &ok );
2774 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2775 Qt::BrushStyle b = Qt::SolidPattern;
2780 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2781 if ( !sizeElem.isNull() )
2784 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2793 const QString &name,
const QColor &color,
const QColor &strokeColor, Qt::PenStyle strokeStyle,
2794 double strokeWidth,
double size )
2797 wellKnownMarkerToSld( doc, element, name, color, strokeColor, strokeStyle, context, strokeWidth, size );
2802 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2803 element.appendChild( markElem );
2805 QDomElement wellKnownNameElem = doc.createElement( QStringLiteral(
"se:WellKnownName" ) );
2806 wellKnownNameElem.appendChild( doc.createTextNode( name ) );
2807 markElem.appendChild( wellKnownNameElem );
2810 if ( color.isValid() )
2812 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2813 fillToSld( doc, fillElem, context, Qt::SolidPattern, color );
2814 markElem.appendChild( fillElem );
2818 if ( strokeColor.isValid() )
2820 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
2821 lineToSld( doc, strokeElem, strokeStyle, strokeColor, context, strokeWidth );
2822 markElem.appendChild( strokeElem );
2828 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2830 element.appendChild( sizeElem );
2835 QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle,
2836 double &strokeWidth,
double &size )
2840 name = QStringLiteral(
"square" );
2842 strokeColor = QColor( 0, 0, 0 );
2846 const QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2847 if ( markElem.isNull() )
2850 const QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
2851 if ( !wellKnownNameElem.isNull() )
2853 name = wellKnownNameElem.firstChild().nodeValue();
2858 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2859 Qt::BrushStyle b = Qt::SolidPattern;
2864 QDomElement strokeElem = markElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2865 lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth );
2869 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2870 if ( !sizeElem.isNull() )
2873 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2889 if ( !rotationFunc.isEmpty() )
2891 QDomElement rotationElem = doc.createElement( QStringLiteral(
"se:Rotation" ) );
2893 element.appendChild( rotationElem );
2899 QDomElement rotationElem = element.firstChildElement( QStringLiteral(
"Rotation" ) );
2900 if ( !rotationElem.isNull() )
2915 if ( !alphaFunc.isEmpty() )
2917 QDomElement opacityElem = doc.createElement( QStringLiteral(
"se:Opacity" ) );
2919 element.appendChild( opacityElem );
2925 QDomElement opacityElem = element.firstChildElement( QStringLiteral(
"Opacity" ) );
2926 if ( !opacityElem.isNull() )
2935 if ( offset.isNull() )
2938 QDomElement displacementElem = doc.createElement( QStringLiteral(
"se:Displacement" ) );
2939 element.appendChild( displacementElem );
2941 QDomElement dispXElem = doc.createElement( QStringLiteral(
"se:DisplacementX" ) );
2942 dispXElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.x(), 2 ) ) );
2944 QDomElement dispYElem = doc.createElement( QStringLiteral(
"se:DisplacementY" ) );
2945 dispYElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.y(), 2 ) ) );
2947 displacementElem.appendChild( dispXElem );
2948 displacementElem.appendChild( dispYElem );
2955 QDomElement anchorElem = doc.createElement( QStringLiteral(
"se:AnchorPoint" ) );
2956 element.appendChild( anchorElem );
2958 QDomElement anchorXElem = doc.createElement( QStringLiteral(
"se:AnchorPointX" ) );
2959 anchorXElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.x() ) ) );
2961 QDomElement anchorYElem = doc.createElement( QStringLiteral(
"se:AnchorPointY" ) );
2962 anchorYElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.y() ) ) );
2964 anchorElem.appendChild( anchorXElem );
2965 anchorElem.appendChild( anchorYElem );
2970 offset = QPointF( 0, 0 );
2972 const QDomElement displacementElem = element.firstChildElement( QStringLiteral(
"Displacement" ) );
2973 if ( displacementElem.isNull() )
2976 const QDomElement dispXElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementX" ) );
2977 if ( !dispXElem.isNull() )
2980 const double offsetX = dispXElem.firstChild().nodeValue().toDouble( &ok );
2982 offset.setX( offsetX );
2985 const QDomElement dispYElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementY" ) );
2986 if ( !dispYElem.isNull() )
2989 const double offsetY = dispYElem.firstChild().nodeValue().toDouble( &ok );
2991 offset.setY( offsetY );
2998 const QString &label,
const QFont &font,
2999 const QColor &color,
double size )
3002 labelTextToSld( doc, element, label, font, context, color, size );
3007 QDomElement labelElem = doc.createElement( QStringLiteral(
"se:Label" ) );
3008 labelElem.appendChild( doc.createTextNode( label ) );
3009 element.appendChild( labelElem );
3011 QDomElement fontElem = doc.createElement( QStringLiteral(
"se:Font" ) );
3012 element.appendChild( fontElem );
3016 fontElem.appendChild( createSldParameterElement( doc,
"font-style",
encodeSldFontStyle( font.style() ) ) );
3017 fontElem.appendChild( createSldParameterElement( doc,
"font-weight",
encodeSldFontWeight( font.weight() ) ) );
3022 if ( color.isValid() )
3024 QDomElement fillElem = doc.createElement( QStringLiteral(
"Fill" ) );
3025 fillToSld( doc, fillElem, context, Qt::SolidPattern, color );
3026 element.appendChild( fillElem );
3031 Qt::PenJoinStyle joinStyle,
3032 Qt::PenCapStyle capStyle,
3034 const QVector<qreal> *dashPattern )
3037 penStyle.append(
"PEN(" );
3038 penStyle.append(
"c:" );
3039 penStyle.append(
c.name() );
3040 penStyle.append(
",w:" );
3042 penStyle.append( QString::number( width * mmScaleFactor ) );
3043 penStyle.append(
"mm" );
3046 if ( dashPattern && !dashPattern->isEmpty() )
3048 penStyle.append(
",p:\"" );
3049 QVector<qreal>::const_iterator pIt = dashPattern->constBegin();
3050 for ( ; pIt != dashPattern->constEnd(); ++pIt )
3052 if ( pIt != dashPattern->constBegin() )
3054 penStyle.append(
' ' );
3056 penStyle.append( QString::number( *pIt * mapUnitScaleFactor ) );
3057 penStyle.append(
'g' );
3059 penStyle.append(
'\"' );
3063 penStyle.append(
",cap:" );
3067 penStyle.append(
'p' );
3070 penStyle.append(
'r' );
3074 penStyle.append(
'b' );
3078 penStyle.append(
",j:" );
3079 switch ( joinStyle )
3082 penStyle.append(
'b' );
3085 penStyle.append(
'r' );
3089 penStyle.append(
'm' );
3095 penStyle.append(
",dp:" );
3096 penStyle.append( QString::number( offset * mapUnitScaleFactor ) );
3097 penStyle.append(
'g' );
3100 penStyle.append(
')' );
3107 brushStyle.append(
"BRUSH(" );
3108 brushStyle.append(
"fc:" );
3109 brushStyle.append( fillColor.name() );
3110 brushStyle.append(
')' );
3122 if ( geomFunc.isEmpty() )
3125 QDomElement geometryElem = doc.createElement( QStringLiteral(
"Geometry" ) );
3126 element.appendChild( geometryElem );
3156 QDomElement geometryElem = element.firstChildElement( QStringLiteral(
"Geometry" ) );
3157 if ( geometryElem.isNull() )
3175 context.
pushError( QObject::tr(
"Parser error encountered when converting expression to SLD: %1 - Expression was: %2" ).arg( expr.
parserErrorString(), function ) );
3179 if ( !filterElem.isNull() )
3180 element.appendChild( filterElem );
3193 if ( function == QLatin1String(
"ELSE" ) )
3196 element.appendChild( filterElem );
3205 context.
pushError( QObject::tr(
"Parser error encountered when converting expression to SLD: %1 - Expression was: %2" ).arg( expr.
parserErrorString(), function ) );
3209 if ( !filterElem.isNull() )
3210 element.appendChild( filterElem );
3218 QDomElement elem = element;
3219 if ( element.tagName() != QLatin1String(
"Filter" ) )
3221 const QDomNodeList filterNodes = element.elementsByTagName( QStringLiteral(
"Filter" ) );
3222 if ( !filterNodes.isEmpty() )
3224 elem = filterNodes.at( 0 ).toElement();
3228 if ( elem.isNull() )
3253 const QString &path,
const QString &format )
3257 QDomElement onlineResourceElem = doc.createElement( QStringLiteral(
"se:OnlineResource" ) );
3258 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
3259 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:href" ), url );
3260 element.appendChild( onlineResourceElem );
3262 QDomElement formatElem = doc.createElement( QStringLiteral(
"se:Format" ) );
3263 formatElem.appendChild( doc.createTextNode( format ) );
3264 element.appendChild( formatElem );
3271 const QDomElement onlineResourceElem = element.firstChildElement( QStringLiteral(
"OnlineResource" ) );
3272 if ( onlineResourceElem.isNull() )
3275 path = QUrl::fromPercentEncoding( onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) ).toUtf8() );
3277 const QDomElement formatElem = element.firstChildElement( QStringLiteral(
"Format" ) );
3278 if ( formatElem.isNull() )
3281 format = formatElem.firstChild().nodeValue();
3288 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:SvgParameter" ) );
3289 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
3290 nodeElem.appendChild( doc.createTextNode( value ) );
3299 QDomElement paramElem = element.firstChildElement();
3300 while ( !paramElem.isNull() )
3302 if ( paramElem.localName() == QLatin1String(
"SvgParameter" ) || paramElem.localName() == QLatin1String(
"CssParameter" ) )
3304 const QString name = paramElem.attribute( QStringLiteral(
"name" ) );
3305 if ( paramElem.firstChild().nodeType() == QDomNode::TextNode )
3307 value = paramElem.firstChild().nodeValue();
3311 if ( paramElem.firstChild().nodeType() == QDomNode::ElementNode &&
3312 paramElem.firstChild().localName() == QLatin1String(
"Literal" ) )
3315 value = paramElem.firstChild().firstChild().nodeValue();
3319 QgsDebugError( QStringLiteral(
"unexpected child of %1" ).arg( paramElem.localName() ) );
3323 if ( !name.isEmpty() && !value.isEmpty() )
3324 params[ name ] = value;
3327 paramElem = paramElem.nextSiblingElement();
3335 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:VendorOption" ) );
3336 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
3337 nodeElem.appendChild( doc.createTextNode( value ) );
3345 QDomElement paramElem = element.firstChildElement( QStringLiteral(
"VendorOption" ) );
3346 while ( !paramElem.isNull() )
3348 const QString name = paramElem.attribute( QStringLiteral(
"name" ) );
3349 const QString value = paramElem.firstChild().nodeValue();
3351 if ( !name.isEmpty() && !value.isEmpty() )
3352 params[ name ] = value;
3354 paramElem = paramElem.nextSiblingElement( QStringLiteral(
"VendorOption" ) );
3364 if ( newSymbols.userType() == QMetaType::Type::QVariantMap )
3366 return newSymbols.toMap();
3373 QDomElement e = element.firstChildElement();
3374 while ( !e.isNull() )
3376 if ( e.tagName() == QLatin1String(
"prop" ) )
3378 const QString propKey = e.attribute( QStringLiteral(
"k" ) );
3379 const QString propValue = e.attribute( QStringLiteral(
"v" ) );
3380 props[propKey] = propValue;
3382 e = e.nextSiblingElement();
3399 QDomElement e = element.firstChildElement();
3401 while ( !e.isNull() )
3403 if ( e.tagName() == QLatin1String(
"symbol" ) )
3407 symbols.insert( e.attribute( QStringLiteral(
"name" ) ), symbol.release() );
3413 e = e.nextSiblingElement();
3420 QStringList subsymbols;
3422 for ( QMap<QString, QgsSymbol *>::iterator it = symbols.begin(); it != symbols.end(); ++it )
3424 if ( it.key()[0] !=
'@' )
3428 subsymbols.append( it.key() );
3430 QStringList parts = it.key().split(
'@' );
3431 if ( parts.count() < 3 )
3433 QgsDebugError(
"found subsymbol with invalid name: " + it.key() );
3437 const QString symname = parts[1];
3438 const int symlayer = parts[2].toInt();
3440 if ( !symbols.contains( symname ) )
3442 QgsDebugError(
"subsymbol references invalid symbol: " + symname );
3450 QgsDebugError(
"subsymbol references invalid symbol layer: " + QString::number( symlayer ) );
3459 QgsDebugError(
"symbol layer refused subsymbol: " + it.key() );
3466 for (
int i = 0; i < subsymbols.count(); i++ )
3467 symbols.take( subsymbols[i] );
3474 QDomElement symbolsElem = doc.createElement( tagName );
3477 for ( QMap<QString, QgsSymbol *>::iterator its = symbols.begin(); its != symbols.end(); ++its )
3479 const QDomElement symEl =
saveSymbol( its.key(), its.value(), doc, context );
3480 symbolsElem.appendChild( symEl );
3488 qDeleteAll( symbols );
3497 std::unique_ptr< QMimeData >mimeData(
new QMimeData );
3499 QDomDocument symbolDoc;
3501 symbolDoc.appendChild( symbolElem );
3502 mimeData->setText( symbolDoc.toString() );
3505 mimeData->setColorData( symbol->
color() );
3507 return mimeData.release();
3515 const QString text = data->text();
3516 if ( !text.isEmpty() )
3521 if ( doc.setContent( text ) )
3523 elem = doc.documentElement();
3525 if ( elem.nodeName() != QLatin1String(
"symbol" ) )
3526 elem = elem.firstChildElement( QStringLiteral(
"symbol" ) );
3537 const QString rampType = element.attribute( QStringLiteral(
"type" ) );
3562 QDomElement rampEl = doc.createElement( QStringLiteral(
"colorramp" ) );
3563 rampEl.setAttribute( QStringLiteral(
"type" ), ramp->
type() );
3564 rampEl.setAttribute( QStringLiteral(
"name" ), name );
3572 QVariantMap rampMap;
3574 rampMap.insert( QStringLiteral(
"type" ), ramp->
type() );
3575 rampMap.insert( QStringLiteral(
"name" ), name );
3577 const QVariantMap properties = ramp->
properties();
3579 QVariantMap propertyMap;
3580 for (
auto property = properties.constBegin();
property != properties.constEnd(); ++property )
3582 propertyMap.insert( property.key(),
property.value() );
3585 rampMap.insert( QStringLiteral(
"properties" ), propertyMap );
3591 const QVariantMap rampMap = value.toMap();
3593 const QString rampType = rampMap.value( QStringLiteral(
"type" ) ).toString();
3596 const QVariantMap propertyMap = rampMap.value( QStringLiteral(
"properties" ) ).toMap();
3599 for (
auto property = propertyMap.constBegin();
property != propertyMap.constEnd(); ++property )
3601 props.insert( property.key(),
property.value().toString() );
3623 if ( !color.isValid() )
3630 return color.name();
3635 QList<QColor> colors;
3638 const thread_local QRegularExpression sepCommaSpaceRegExp(
"(,|\\s)" );
3639 QStringList components = colorStr.simplified().split( sepCommaSpaceRegExp );
3640 QStringList::iterator it = components.begin();
3641 for ( ; it != components.end(); ++it )
3643 const QColor result =
parseColor( *it,
true );
3644 if ( result.isValid() )
3649 if ( colors.length() > 0 )
3655 const thread_local QRegularExpression sepCommaRegExp(
"(,|\n)" );
3656 components = colorStr.split( sepCommaRegExp );
3657 it = components.begin();
3658 for ( ; it != components.end(); ++it )
3660 const QColor result =
parseColor( *it,
true );
3661 if ( result.isValid() )
3666 if ( colors.length() > 0 )
3672 components = colorStr.simplified().split( QString(
' ' ) );
3673 it = components.begin();
3674 for ( ; it != components.end(); ++it )
3676 const QColor result =
parseColor( *it,
true );
3677 if ( result.isValid() )
3682 if ( colors.length() > 0 )
3688 components = colorStr.split(
'\n' );
3689 it = components.begin();
3690 for ( ; it != components.end(); ++it )
3692 const QColor result =
parseColor( *it,
true );
3693 if ( result.isValid() )
3706 QMimeData *mimeData =
new QMimeData;
3707 mimeData->setColorData( QVariant( color ) );
3708 mimeData->setText( color.name() );
3718 if ( mimeData->hasColor() )
3720 QColor mimeColor = mimeData->colorData().value<QColor>();
3721 if ( mimeColor.isValid() )
3729 if ( mimeData->hasText() )
3733 if ( textColor.isValid() )
3751 if ( data->hasFormat( QStringLiteral(
"text/xml" ) ) )
3754 const QByteArray encodedData = data->data( QStringLiteral(
"text/xml" ) );
3755 QDomDocument xmlDoc;
3756 xmlDoc.setContent( encodedData );
3758 const QDomElement dragDataElem = xmlDoc.documentElement();
3759 if ( dragDataElem.tagName() == QLatin1String(
"ColorSchemeModelDragData" ) )
3761 const QDomNodeList nodeList = dragDataElem.childNodes();
3762 const int nChildNodes = nodeList.size();
3763 QDomElement currentElem;
3765 for (
int i = 0; i < nChildNodes; ++i )
3767 currentElem = nodeList.at( i ).toElement();
3768 if ( currentElem.isNull() )
3773 QPair< QColor, QString> namedColor;
3775 namedColor.second = currentElem.attribute( QStringLiteral(
"label" ), QString() );
3777 mimeColors << namedColor;
3782 if ( mimeColors.length() == 0 && data->hasFormat( QStringLiteral(
"application/x-colorobject-list" ) ) )
3785 const QByteArray encodedData = data->data( QStringLiteral(
"application/x-colorobject-list" ) );
3786 QDomDocument xmlDoc;
3787 xmlDoc.setContent( encodedData );
3789 const QDomNodeList colorsNodes = xmlDoc.elementsByTagName( QStringLiteral(
"colors" ) );
3790 if ( colorsNodes.length() > 0 )
3792 const QDomElement colorsElem = colorsNodes.at( 0 ).toElement();
3793 const QDomNodeList colorNodeList = colorsElem.childNodes();
3794 const int nChildNodes = colorNodeList.size();
3795 QDomElement currentElem;
3797 for (
int i = 0; i < nChildNodes; ++i )
3800 currentElem = colorNodeList.at( i ).toElement();
3801 if ( currentElem.isNull() )
3806 const QDomNodeList colorNodes = currentElem.elementsByTagName( QStringLiteral(
"color" ) );
3807 const QDomNodeList nameNodes = currentElem.elementsByTagName( QStringLiteral(
"name" ) );
3809 if ( colorNodes.length() > 0 )
3811 const QDomElement colorElem = colorNodes.at( 0 ).toElement();
3813 const QStringList colorParts = colorElem.text().simplified().split(
' ' );
3814 if ( colorParts.length() < 3 )
3819 const int red = colorParts.at( 0 ).toDouble() * 255;
3820 const int green = colorParts.at( 1 ).toDouble() * 255;
3821 const int blue = colorParts.at( 2 ).toDouble() * 255;
3822 QPair< QColor, QString> namedColor;
3823 namedColor.first = QColor( red, green, blue );
3824 if ( nameNodes.length() > 0 )
3826 const QDomElement nameElem = nameNodes.at( 0 ).toElement();
3827 namedColor.second = nameElem.text();
3829 mimeColors << namedColor;
3835 if ( mimeColors.length() == 0 && data->hasText() )
3839 QList< QColor >::iterator it = parsedColors.begin();
3840 for ( ; it != parsedColors.end(); ++it )
3842 mimeColors << qMakePair( *it, QString() );
3846 if ( mimeColors.length() == 0 && data->hasColor() )
3849 const QColor mimeColor = data->colorData().value<QColor>();
3850 if ( mimeColor.isValid() )
3852 mimeColors << qMakePair( mimeColor, QString() );
3862 QMimeData *mimeData =
new QMimeData();
3863 QDomDocument xmlDoc;
3864 QDomElement xmlRootElement = xmlDoc.createElement( QStringLiteral(
"ColorSchemeModelDragData" ) );
3865 xmlDoc.appendChild( xmlRootElement );
3867 QgsNamedColorList::const_iterator colorIt = colorList.constBegin();
3868 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3870 QDomElement namedColor = xmlDoc.createElement( QStringLiteral(
"NamedColor" ) );
3872 namedColor.setAttribute( QStringLiteral(
"label" ), ( *colorIt ).second );
3873 xmlRootElement.appendChild( namedColor );
3875 mimeData->setData( QStringLiteral(
"text/xml" ), xmlDoc.toByteArray() );
3883 colorIt = colorList.constBegin();
3884 QStringList colorListString;
3885 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3887 colorListString << ( *colorIt ).first.name();
3889 mimeData->setText( colorListString.join( QLatin1Char(
'\n' ) ) );
3892 if ( colorList.length() > 0 )
3894 mimeData->setColorData( QVariant( colorList.at( 0 ).first ) );
3902 if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3907 QTextStream stream( &file );
3908#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
3909 stream.setCodec(
"UTF-8" );
3912 stream <<
"GIMP Palette" << Qt::endl;
3913 if ( paletteName.isEmpty() )
3915 stream <<
"Name: QGIS Palette" << Qt::endl;
3919 stream <<
"Name: " << paletteName << Qt::endl;
3921 stream <<
"Columns: 4" << Qt::endl;
3922 stream <<
'#' << Qt::endl;
3924 for ( QgsNamedColorList::ConstIterator colorIt = colors.constBegin(); colorIt != colors.constEnd(); ++colorIt )
3926 const QColor color = ( *colorIt ).first;
3927 if ( !color.isValid() )
3931 stream << QStringLiteral(
"%1 %2 %3" ).arg( color.red(), 3 ).arg( color.green(), 3 ).arg( color.blue(), 3 );
3932 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << Qt::endl;
3943 if ( !file.open( QIODevice::ReadOnly ) )
3946 return importedColors;
3949 QTextStream in( &file );
3950#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
3951 in.setCodec(
"UTF-8" );
3954 QString line = in.readLine();
3955 if ( !line.startsWith( QLatin1String(
"GIMP Palette" ) ) )
3958 return importedColors;
3962 while ( !in.atEnd() && !line.startsWith( QLatin1String(
"Name:" ) ) && !line.startsWith(
'#' ) )
3964 line = in.readLine();
3966 if ( line.startsWith( QLatin1String(
"Name:" ) ) )
3968 const thread_local QRegularExpression nameRx(
"Name:\\s*(\\S.*)$" );
3969 const QRegularExpressionMatch match = nameRx.match( line );
3970 if ( match.hasMatch() )
3972 name = match.captured( 1 );
3977 while ( !in.atEnd() && !line.startsWith(
'#' ) )
3979 line = in.readLine();
3984 return importedColors;
3988 const thread_local QRegularExpression rx(
"^\\s*(\\d+)\\s+(\\d+)\\s+(\\d+)(\\s.*)?$" );
3989 while ( !in.atEnd() )
3991 line = in.readLine();
3992 const QRegularExpressionMatch match = rx.match( line );
3993 if ( !match.hasMatch() )
3997 const int red = match.captured( 1 ).toInt();
3998 const int green = match.captured( 2 ).toInt();
3999 const int blue = match.captured( 3 ).toInt();
4000 const QColor color = QColor( red, green, blue );
4001 if ( !color.isValid() )
4008 if ( rx.captureCount() > 3 )
4010 label = match.captured( 4 ).simplified();
4017 importedColors << qMakePair( color, label );
4022 return importedColors;
4035 const thread_local QRegularExpression hexColorAlphaRx(
"^\\s*#?([0-9a-fA-F]{6})([0-9a-fA-F]{2})\\s*$" );
4036 QRegularExpressionMatch match = hexColorAlphaRx.match( colorStr );
4039 if ( !match.hasMatch() && QColor::isValidColor( colorStr ) )
4042 parsedColor.setNamedColor( colorStr );
4043 if ( parsedColor.isValid() )
4045 containsAlpha =
false;
4051 if ( match.hasMatch() )
4053 const QString hexColor = match.captured( 1 );
4054 parsedColor.setNamedColor( QStringLiteral(
"#" ) + hexColor );
4056 const int alphaHex = match.captured( 2 ).toInt( &alphaOk, 16 );
4058 if ( parsedColor.isValid() && alphaOk )
4060 parsedColor.setAlpha( alphaHex );
4061 containsAlpha =
true;
4069 const thread_local QRegularExpression hexColorRx2(
"^\\s*(?:[0-9a-fA-F]{3}){1,2}\\s*$" );
4070 if ( colorStr.indexOf( hexColorRx2 ) != -1 )
4073 parsedColor.setNamedColor( QStringLiteral(
"#" ) + colorStr );
4074 if ( parsedColor.isValid() )
4076 containsAlpha =
false;
4083 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*$" );
4084 match = rgbFormatRx.match( colorStr );
4085 if ( match.hasMatch() )
4090 const int r = match.captured( 1 ).toInt( &rOk );
4091 const int g = match.captured( 2 ).toInt( &gOk );
4092 const int b = match.captured( 3 ).toInt( &bOk );
4094 if ( !rOk || !gOk || !bOk )
4096 const float rFloat = match.captured( 1 ).toFloat();
4097 const float gFloat = match.captured( 2 ).toFloat();
4098 const float bFloat = match.captured( 3 ).toFloat();
4099 parsedColor.setRgbF( rFloat / 255.0, gFloat / 255.0, bFloat / 255.0 );
4103 parsedColor.setRgb( r, g, b );
4106 if ( parsedColor.isValid() )
4108 containsAlpha =
false;
4114 const thread_local QRegularExpression hslFormatRx(
"^\\s*hsl\\(?\\s*(\\d+(?:\\.\\d*)?)\\s*,\\s*(\\d+(?:\\.\\d*)?)\\s*%\\s*,\\s*(\\d+(?:\\.\\d*)?)\\s*%\\s*\\)?\\s*;?\\s*$" );
4115 match = hslFormatRx.match( colorStr );
4116 if ( match.hasMatch() )
4121 const int h = match.captured( 1 ).toInt( &hOk );
4122 const int s = match.captured( 2 ).toInt( &sOk );
4123 const int l = match.captured( 3 ).toInt( &lOk );
4125 if ( !hOk || !sOk || !lOk )
4127 const float hFloat = match.captured( 1 ).toFloat();
4128 const float sFloat = match.captured( 2 ).toFloat();
4129 const float lFloat = match.captured( 3 ).toFloat();
4130 parsedColor.setHslF( hFloat / 360.0, sFloat / 100.0, lFloat / 100.0 );
4134 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0 );
4136 if ( parsedColor.isValid() )
4138 containsAlpha =
false;
4144 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*$" );
4145 match = rgbPercentFormatRx.match( colorStr );
4146 if ( match.hasMatch() )
4148 const double r = match.captured( 1 ).toDouble() / 100;
4149 const double g = match.captured( 2 ).toDouble() / 100;
4150 const double b = match.captured( 3 ).toDouble() / 100;
4151 parsedColor.setRgbF( r, g, b );
4152 if ( parsedColor.isValid() )
4154 containsAlpha =
false;
4160 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*$" );
4161 match = rgbaFormatRx.match( colorStr );
4162 if ( match.hasMatch() )
4167 const int r = match.captured( 1 ).toInt( &rOk );
4168 const int g = match.captured( 2 ).toInt( &gOk );
4169 const int b = match.captured( 3 ).toInt( &bOk );
4170 const double aDouble = match.captured( 4 ).toDouble();
4172 if ( !rOk || !gOk || !bOk )
4174 const float rFloat = match.captured( 1 ).toFloat();
4175 const float gFloat = match.captured( 2 ).toFloat();
4176 const float bFloat = match.captured( 3 ).toFloat();
4177 parsedColor.setRgbF( rFloat / 255.0, gFloat / 255.0, bFloat / 255.0, aDouble );
4181 const int a =
static_cast< int >( std::round( match.captured( 4 ).toDouble() * 255.0 ) );
4182 parsedColor.setRgb( r, g, b, a );
4184 if ( parsedColor.isValid() )
4186 containsAlpha =
true;
4192 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*$" );
4193 match = rgbaPercentFormatRx.match( colorStr );
4194 if ( match.hasMatch() )
4196 const double r = match.captured( 1 ).toDouble() / 100;
4197 const double g = match.captured( 2 ).toDouble() / 100;
4198 const double b = match.captured( 3 ).toDouble() / 100;
4199 const double a = match.captured( 4 ).toDouble();
4200 parsedColor.setRgbF( r, g, b, a );
4201 if ( parsedColor.isValid() )
4203 containsAlpha =
true;
4209 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*$" );
4210 match = hslaPercentFormatRx.match( colorStr );
4211 if ( match.hasMatch() )
4216 const int h = match.captured( 1 ).toInt( &hOk );
4217 const int s = match.captured( 2 ).toInt( &sOk );
4218 const int l = match.captured( 3 ).toInt( &lOk );
4219 const double aDouble = match.captured( 4 ).toDouble();
4221 if ( !hOk || !sOk || !lOk )
4223 const float hFloat = match.captured( 1 ).toFloat();
4224 const float sFloat = match.captured( 2 ).toFloat();
4225 const float lFloat = match.captured( 3 ).toFloat();
4226 parsedColor.setHslF( hFloat / 360.0, sFloat / 100.0, lFloat / 100.0, aDouble );
4230 const int a = std::round( aDouble * 255.0 );
4231 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0, a );
4234 if ( parsedColor.isValid() )
4236 containsAlpha =
true;
4253 const QImage::Format format = image->format();
4254 if ( format != QImage::Format_ARGB32_Premultiplied && format != QImage::Format_ARGB32 )
4261 for (
int heightIndex = 0; heightIndex < image->height(); ++heightIndex )
4263 QRgb *scanLine =
reinterpret_cast< QRgb *
>( image->scanLine( heightIndex ) );
4264 for (
int widthIndex = 0; widthIndex < image->width(); ++widthIndex )
4266 myRgb = scanLine[widthIndex];
4267 if ( format == QImage::Format_ARGB32_Premultiplied )
4268 scanLine[widthIndex] = qRgba( opacity * qRed( myRgb ), opacity * qGreen( myRgb ), opacity * qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4270 scanLine[widthIndex] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4278 const int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
4279 const int alpha = ( radius < 1 ) ? 16 : ( radius > 17 ) ? 1 : tab[radius - 1];
4281 if ( image.format() != QImage::Format_ARGB32_Premultiplied
4282 && image.format() != QImage::Format_RGB32 )
4284 image = image.convertToFormat( QImage::Format_ARGB32_Premultiplied );
4287 const int r1 = rect.top();
4288 const int r2 = rect.bottom();
4289 const int c1 = rect.left();
4290 const int c2 = rect.right();
4292 const int bpl = image.bytesPerLine();
4300 i1 = i2 = ( QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3 );
4302 for (
int col = c1; col <= c2; col++ )
4304 p = image.scanLine( r1 ) + col * 4;
4305 for (
int i = i1; i <= i2; i++ )
4306 rgba[i] = p[i] << 4;
4309 for (
int j = r1; j < r2; j++, p += bpl )
4310 for (
int i = i1; i <= i2; i++ )
4311 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4314 for (
int row = r1; row <= r2; row++ )
4316 p = image.scanLine( row ) + c1 * 4;
4317 for (
int i = i1; i <= i2; i++ )
4318 rgba[i] = p[i] << 4;
4321 for (
int j = c1; j < c2; j++, p += 4 )
4322 for (
int i = i1; i <= i2; i++ )
4323 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4326 for (
int col = c1; col <= c2; col++ )
4328 p = image.scanLine( r2 ) + col * 4;
4329 for (
int i = i1; i <= i2; i++ )
4330 rgba[i] = p[i] << 4;
4333 for (
int j = r1; j < r2; j++, p -= bpl )
4334 for (
int i = i1; i <= i2; i++ )
4335 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4338 for (
int row = r1; row <= r2; row++ )
4340 p = image.scanLine( row ) + c2 * 4;
4341 for (
int i = i1; i <= i2; i++ )
4342 rgba[i] = p[i] << 4;
4345 for (
int j = c1; j < c2; j++, p -= 4 )
4346 for (
int i = i1; i <= i2; i++ )
4347 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4353 if ( alpha != 255 && alpha > 0 )
4357 const double alphaFactor = alpha / 255.;
4358 int r = 0, g = 0, b = 0;
4359 rgb.getRgb( &r, &g, &b );
4364 rgb.setRgb( r, g, b, alpha );
4366 else if ( alpha == 0 )
4368 rgb.setRgb( 0, 0, 0, 0 );
4377 if ( !simpleFill || !simpleLine )
4401 if ( simpleLine->
offset() )
4419 if ( order == Qt::AscendingOrder )
4433 const double dx = directionPoint.x() - startPoint.x();
4434 const double dy = directionPoint.y() - startPoint.y();
4435 const double length = std::sqrt( dx * dx + dy * dy );
4436 const double scaleFactor = distance / length;
4437 return QPointF( startPoint.x() + dx * scaleFactor, startPoint.y() + dy * scaleFactor );
4447 for (
int i = 0; i < svgPaths.size(); i++ )
4449 const QDir dir( svgPaths[i] );
4450 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4451 for (
const QString &item : svgSubPaths )
4453 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4456 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4457 for (
const QString &item : svgFiles )
4460 list.append( dir.path() +
'/' + item );
4472 QStringList svgPaths;
4473 svgPaths.append( directory );
4475 for (
int i = 0; i < svgPaths.size(); i++ )
4477 const QDir dir( svgPaths[i] );
4478 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4479 for (
const QString &item : svgSubPaths )
4481 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4484 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4485 for (
const QString &item : svgFiles )
4487 list.append( dir.path() +
'/' + item );
4499 if ( n.startsWith( QLatin1String(
"base64:" ) ) )
4503 if ( QFileInfo::exists( n ) )
4504 return QFileInfo( n ).canonicalFilePath();
4508 if ( name.contains( QLatin1String(
"://" ) ) )
4510 const QUrl url( name );
4511 if ( url.isValid() && !url.scheme().isEmpty() )
4513 if ( url.scheme().compare( QLatin1String(
"file" ), Qt::CaseInsensitive ) == 0 )
4516 name = url.toLocalFile();
4517 if ( QFile( name ).exists() )
4519 return QFileInfo( name ).canonicalFilePath();
4533 for (
int i = 0; i < svgPaths.size(); i++ )
4535 QString svgPath = svgPaths[i];
4536 if ( svgPath.endsWith( QChar(
'/' ) ) )
4547 const QString myLocalPath = svgPath + QDir::separator() + name;
4550 if ( QFile( myLocalPath ).exists() )
4553 return QFileInfo( myLocalPath ).canonicalFilePath();
4557 return pathResolver.
readPath( name );
4565 if ( p.startsWith( QLatin1String(
"base64:" ) ) )
4568 if ( !QFileInfo::exists( p ) )
4571 QString path = QFileInfo( p ).canonicalFilePath();
4575 bool isInSvgPaths =
false;
4576 for (
int i = 0; i < svgPaths.size(); i++ )
4578 const QString dir = QFileInfo( svgPaths[i] ).canonicalFilePath();
4580 if ( !dir.isEmpty() && path.startsWith( dir ) )
4582 path = path.mid( dir.size() + 1 );
4583 isInSvgPaths =
true;
4596 const double *srcX = line->
xData();
4597 const double *srcY = line->
yData();
4599 QPolygonF thisRes( count );
4600 QPointF *dest = thisRes.data();
4601 for (
int i = 0; i < count; ++i )
4603 *dest++ = QPointF( *srcX++, *srcY++ );
4610 if (
const QgsLineString *line = qgsgeometry_cast< const QgsLineString * >( curve ) )
4616 const std::unique_ptr< QgsLineString > straightened( curve->
curveToLine() );
4640 points << QPointF( ( *it ).x(), ( *it ).y() );
4644 points << QPointF( 0, 0 );
4646 return QList< QList<QPolygonF> >() << ( QList< QPolygonF >() << points );
4651 QList< QList<QPolygonF> > res;
4656 res << ( QList< QPolygonF >() <<
curveToPolygonF( qgsgeometry_cast< const QgsCurve * >( *it ) ) );
4664 QList< QList<QPolygonF> > res;
4668 QList<QPolygonF> thisPart;
4669 const QgsCurvePolygon *surface = qgsgeometry_cast< const QgsCurvePolygon * >( *it );
4687 return QList< QList<QPolygonF> >();
4690 return QList< QList<QPolygonF> >();
4697 double cx = 0, cy = 0;
4698 double area, sum = 0;
4699 for (
int i = points.count() - 1, j = 0; j < points.count(); i = j++ )
4701 const QPointF &p1 = points[i];
4702 const QPointF &p2 = points[j];
4703 area = p1.x() * p2.y() - p1.y() * p2.x();
4705 cx += ( p1.x() + p2.x() ) * area;
4706 cy += ( p1.y() + p2.y() ) * area;
4713 if ( points.count() >= 2 )
4714 return QPointF( ( points[0].x() + points[1].x() ) / 2, ( points[0].y() + points[1].y() ) / 2 );
4715 else if ( points.count() == 1 )
4723 return QPointF( cx, cy );
4730 if ( ( rings && rings->count() > 0 ) || !
pointInPolygon( points, centroid ) )
4732 unsigned int i, pointCount = points.count();
4734 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( points[i].x(), points[i].y() );
4740 for (
auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
4742 pointCount = ( *ringIt ).count();
4744 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( ( *ringIt )[i].x(), ( *ringIt )[i].y() );
4750 if ( !pointOnSurfaceGeom.
isNull() )
4753 centroid.
setX( point.
x() );
4754 centroid.setY( point.
y() );
4759 return QPointF( centroid.x(), centroid.y() );
4764 bool inside =
false;
4766 const double x = point.x();
4767 const double y = point.y();
4769 for (
int i = 0, j = points.count() - 1; i < points.count(); i++ )
4771 const QPointF &p1 = points[i];
4772 const QPointF &p2 = points[j];
4777 if ( ( p1.y() < y && p2.y() >= y ) || ( p2.y() < y && p1.y() >= y ) )
4779 if ( p1.x() + ( y - p1.y() ) / ( p2.y() - p1.y() ) * ( p2.x() - p1.x() ) <= x )
4790 if ( polyline.size() < 2 )
4793 double totalLength = 0;
4794 auto it = polyline.begin();
4796 for ( ; it != polyline.end(); ++it )
4798 const QPointF p2 = *it;
4799 const double segmentLength = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4800 totalLength += segmentLength;
4808 if ( polyline.size() < 2 )
4811 double totalLength = 0;
4812 auto it = polyline.begin();
4814 std::vector< double > segmentLengths( polyline.size() - 1 );
4815 auto segmentLengthIt = segmentLengths.begin();
4816 for ( ; it != polyline.end(); ++it )
4818 const QPointF p2 = *it;
4819 *segmentLengthIt = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4820 totalLength += *segmentLengthIt;
4826 if ( startOffset >= 0 && totalLength <= startOffset )
4828 if ( endOffset < 0 && totalLength <= -endOffset )
4831 const double startDistance = startOffset < 0 ? totalLength + startOffset : startOffset;
4832 const double endDistance = endOffset <= 0 ? totalLength + endOffset : endOffset;
4833 QPolygonF substringPoints;
4834 substringPoints.reserve( polyline.size() );
4836 it = polyline.begin();
4837 segmentLengthIt = segmentLengths.begin();
4840 bool foundStart =
false;
4841 if (
qgsDoubleNear( startDistance, 0.0 ) || startDistance < 0 )
4843 substringPoints << p1;
4847 double distanceTraversed = 0;
4848 for ( ; it != polyline.end(); ++it )
4850 const QPointF p2 = *it;
4851 if ( distanceTraversed < startDistance && distanceTraversed + *segmentLengthIt > startDistance )
4854 const double distanceToStart = startDistance - distanceTraversed;
4855 double startX, startY;
4857 substringPoints << QPointF( startX, startY );
4860 if ( foundStart && ( distanceTraversed + *segmentLengthIt > endDistance ) )
4863 const double distanceToEnd = endDistance - distanceTraversed;
4866 if ( substringPoints.last() != QPointF( endX, endY ) )
4867 substringPoints << QPointF( endX, endY );
4869 else if ( foundStart )
4871 if ( substringPoints.last() != QPointF( p2.x(), p2.y() ) )
4872 substringPoints << QPointF( p2.x(), p2.y() );
4875 distanceTraversed += *segmentLengthIt;
4876 if ( distanceTraversed > endDistance )
4883 if ( ( substringPoints.size() < 2 ) || ( substringPoints.size() == 2 && substringPoints.at( 0 ) == substringPoints.at( 1 ) ) )
4886 return substringPoints;
4891 double vertexAngle = M_PI - ( std::atan2( p3.y() - p2.y(), p3.x() - p2.x() ) - std::atan2( p2.y() - p1.y(), p2.x() - p1.x() ) );
4895 return vertexAngle < M_PI * 135.0 / 180.0 || vertexAngle > M_PI * 225.0 / 180.0;
4900 target.reserve( target.size() + line.size() );
4901 for (
const QPointF &pt : line )
4903 if ( !target.empty() && target.last() == pt )
4912 if ( fieldOrExpression.isEmpty() )
4915 auto expr = std::make_unique< QgsExpression >( fieldOrExpression );
4916 if ( !expr->hasParserError() )
4921 Q_ASSERT( !expr->hasParserError() );
4946 QList<double> breaks;
4949 breaks.append( maximum );
4953 const int minimumCount =
static_cast< int >( classes ) / 3;
4954 const double shrink = 0.75;
4955 const double highBias = 1.5;
4956 const double adjustBias = 0.5 + 1.5 * highBias;
4957 const int divisions = classes;
4958 const double h = highBias;
4961 const double dx = maximum - minimum;
4971 cell = std::max( std::fabs( minimum ), std::fabs( maximum ) );
4972 if ( adjustBias >= 1.5 * h + 0.5 )
4974 U = 1 + ( 1.0 / ( 1 + h ) );
4978 U = 1 + ( 1.5 / ( 1 + adjustBias ) );
4980 small = dx < ( cell * U * std::max( 1, divisions ) * 1e-07 * 3.0 );
4987 cell = 9 + cell / 10;
4988 cell = cell * shrink;
4990 if ( minimumCount > 1 )
4992 cell = cell / minimumCount;
4998 if ( divisions > 1 )
5000 cell = cell / divisions;
5003 if ( cell < 20 * 1e-07 )
5008 const double base = std::pow( 10.0, std::floor( std::log10( cell ) ) );
5010 if ( ( 2 * base ) - cell < h * ( cell - unit ) )
5013 if ( ( 5 * base ) - cell < adjustBias * ( cell - unit ) )
5016 if ( ( 10.0 * base ) - cell < h * ( cell - unit ) )
5023 int start = std::floor( minimum / unit + 1e-07 );
5024 int end = std::ceil( maximum / unit - 1e-07 );
5027 while ( start * unit > minimum + ( 1e-07 * unit ) )
5031 while ( end * unit < maximum - ( 1e-07 * unit ) )
5039 int k = std::floor( 0.5 + end - start );
5040 if ( k < minimumCount )
5042 k = minimumCount - k;
5046 start = start - k / 2 + k % 2;
5050 start = start - k / 2;
5051 end = end + k / 2 + k % 2;
5054 const double minimumBreak = start * unit;
5056 const int count = end - start;
5058 breaks.reserve( count );
5059 for (
int i = 1; i < count + 1; i++ )
5061 breaks.append( minimumBreak + i * unit );
5064 if ( breaks.isEmpty() )
5067 if ( breaks.first() < minimum )
5069 breaks[0] = minimum;
5071 if ( breaks.last() > maximum )
5073 breaks[breaks.count() - 1] = maximum;
5078 if ( minimum < 0.0 && maximum > 0.0 )
5080 QList<double> breaksMinusZero;
5081 for (
int i = 0; i < breaks.count(); i++ )
5083 breaksMinusZero.append( breaks[i] - 0.0 );
5086 for (
int i = 1; i < breaks.count(); i++ )
5088 if ( std::abs( breaksMinusZero[i] ) < std::abs( breaksMinusZero[i - 1] ) )
5091 breaks[posOfMin] = 0.0;
5100 bool roundToUnit =
false;
5103 if ( props.contains( QStringLiteral(
"uomScale" ) ) )
5106 scale = props.value( QStringLiteral(
"uomScale" ) ).toDouble( &ok );
5115 if ( props.value( QStringLiteral(
"uom" ) ) == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
5140 scale = 1 / 0.28 * 25.4;
5164 double rescaled = size * scale;
5169 rescaled = std::round( rescaled );
5176 const double x =
rescaleUom( point.x(), unit, props );
5177 const double y =
rescaleUom( point.y(), unit, props );
5178 return QPointF( x, y );
5183 QVector<qreal> result;
5184 QVector<qreal>::const_iterator it = array.constBegin();
5185 for ( ; it != array.constEnd(); ++it )
5187 result.append(
rescaleUom( *it, unit, props ) );
5194 if ( !props.value( QStringLiteral(
"scaleMinDenom" ), QString() ).toString().isEmpty() )
5196 QDomElement scaleMinDenomElem = doc.createElement( QStringLiteral(
"se:MinScaleDenominator" ) );
5197 scaleMinDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMinDenom" ) ).toString().toDouble() ) ) );
5198 ruleElem.appendChild( scaleMinDenomElem );
5201 if ( !props.value( QStringLiteral(
"scaleMaxDenom" ), QString() ).toString().isEmpty() )
5203 QDomElement scaleMaxDenomElem = doc.createElement( QStringLiteral(
"se:MaxScaleDenominator" ) );
5204 scaleMaxDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMaxDenom" ) ).toString().toDouble() ) ) );
5205 ruleElem.appendChild( scaleMaxDenomElem );
5214 const double parentScaleMinDenom = props.value( QStringLiteral(
"scaleMinDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
5215 if ( !ok || parentScaleMinDenom <= 0 )
5216 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( mScaleMinDenom );
5218 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( std::max( parentScaleMinDenom, mScaleMinDenom ) );
5224 const double parentScaleMaxDenom = props.value( QStringLiteral(
"scaleMaxDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
5225 if ( !ok || parentScaleMaxDenom <= 0 )
5226 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( mScaleMaxDenom );
5228 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( std::min( parentScaleMaxDenom, mScaleMaxDenom ) );
5236 if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
5238 scale = 1.0 / 0.00028;
5240 else if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
5242 scale = 304.8 / 0.28;
5249 return size * scale;
5258 SymbolLayerVisitor(
const QSet<QgsSymbolLayerId> &layerIds )
5259 : mSymbolLayerIds( layerIds )
5272 void visitSymbol(
const QgsSymbol *symbol,
const QString &identifier, QVector<int> rootPath )
5276 QVector<int> indexPath = rootPath;
5277 indexPath.append( idx );
5280 if ( mSymbolLayerIds.contains(
QgsSymbolLayerId( mCurrentRuleKey + identifier, indexPath ) ) )
5282 mSymbolLayers.insert( sl );
5288 visitSymbol( subSymbol, identifier, indexPath );
5297 if ( symbolEntity->symbol() )
5299 visitSymbol( symbolEntity->symbol(), leaf.
identifier, {} );
5305 QString mCurrentRuleKey;
5306 const QSet<QgsSymbolLayerId> &mSymbolLayerIds;
5307 QSet<const QgsSymbolLayer *> mSymbolLayers;
5311 SymbolLayerVisitor visitor( symbolLayerIds );
5312 renderer->
accept( &visitor );
5313 return visitor.mSymbolLayers;
5321 SymbolRefreshRateVisitor()
5333 void visitSymbol(
const QgsSymbol *symbol )
5350 if ( refreshRate == -1 || ( animatedMarker->frameRate() > refreshRate ) )
5351 refreshRate = animatedMarker->frameRate();
5355 visitSymbol( subSymbol );
5363 if (
QgsSymbol *symbol = qgis::down_cast<const QgsStyleSymbolEntity *>( leaf.
entity )->symbol() )
5365 visitSymbol( symbol );
5371 double refreshRate = -1;
5374 SymbolRefreshRateVisitor visitor;
5375 renderer->
accept( &visitor );
5376 return visitor.refreshRate;
5381 if ( !s || !context )
5407 size = markerSymbol->
size( *context );
5409 else if ( lineSymbol )
5411 size = lineSymbol->
width( *context );
5423 if ( minSize > 0 && size < minSize )
5427 else if ( maxSize > 0 && size > maxSize )
5446 else if ( lineSymbol )
5461 QMap<QString, QgsProperty>::const_iterator paramIt = propertiesMap.constBegin();
5462 for ( ; paramIt != propertiesMap.constEnd(); ++paramIt )
5464 properties.insert( paramIt.key(), paramIt.value().valueAsString( context ) );
5472 angleRad = std::fmod( angleRad, M_PI * 2 );
5476 angleRad += M_PI * 2;
5480 struct rationalTangent
5492 static const QList<rationalTangent> __rationalTangents
5494 { 1, 57, 0.01754206006 },
5495 { 3, 86, 0.03486958155 },
5496 { 1, 19, 0.05258306161 },
5497 { 3, 43, 0.06965457373 },
5498 { 7, 80, 0.08727771295 },
5499 { 2, 19, 0.1048769387 },
5500 { 7, 57, 0.1221951707 },
5501 { 9, 64, 0.1397088743 },
5502 { 13, 82, 0.157228051 },
5503 { 3, 17, 0.174672199 },
5504 { 7, 36, 0.1920480172 },
5505 { 17, 80, 0.209385393 },
5506 { 3, 13, 0.2267988481 },
5507 { 1, 4, 0.2449786631 },
5508 { 26, 97, 0.2618852647 },
5509 { 27, 94, 0.2797041525 },
5510 { 26, 85, 0.2968446734 },
5511 { 13, 40, 0.3142318991 },
5512 { 21, 61, 0.3315541619 },
5513 { 4, 11, 0.3487710036 },
5514 { 38, 99, 0.3664967859 },
5515 { 40, 99, 0.383984624 },
5516 { 31, 73, 0.4015805401 },
5517 { 41, 92, 0.4192323938 },
5518 { 7, 15, 0.4366271598 },
5519 { 20, 41, 0.4538440015 },
5520 { 27, 53, 0.4711662643 },
5521 { 42, 79, 0.4886424026 },
5522 { 51, 92, 0.5061751436 },
5523 { 56, 97, 0.5235757641 },
5524 { 3, 5, 0.5404195003 },
5525 { 5, 8, 0.5585993153 },
5526 { 50, 77, 0.5759185996 },
5527 { 29, 43, 0.5933501462 },
5528 { 7, 10, 0.6107259644 },
5529 { 69, 95, 0.6281701124 },
5530 { 52, 69, 0.6458159195 },
5531 { 25, 32, 0.6632029927 },
5532 { 17, 21, 0.6805212247 },
5533 { 73, 87, 0.6981204504 },
5534 { 73, 84, 0.7154487784 },
5535 { 9, 10, 0.7328151018 },
5536 { 83, 89, 0.7505285818 },
5537 { 28, 29, 0.7678561033 },
5538 { 1, 1, 0.7853981634 },
5539 { 29, 28, 0.8029402235 },
5540 { 89, 83, 0.820267745 },
5541 { 10, 9, 0.837981225 },
5542 { 107, 93, 0.855284165 },
5543 { 87, 73, 0.8726758763 },
5544 { 121, 98, 0.8900374031 },
5545 { 32, 25, 0.9075933341 },
5546 { 69, 52, 0.9249804073 },
5547 { 128, 93, 0.9424647244 },
5548 { 10, 7, 0.9600703624 },
5549 { 43, 29, 0.9774461806 },
5550 { 77, 50, 0.9948777272 },
5551 { 8, 5, 1.012197011 },
5552 { 163, 98, 1.029475114 },
5553 { 168, 97, 1.047174539 },
5554 { 175, 97, 1.064668696 },
5555 { 126, 67, 1.082075603 },
5556 { 157, 80, 1.099534652 },
5557 { 203, 99, 1.117049384 },
5558 { 193, 90, 1.134452855 },
5559 { 146, 65, 1.151936673 },
5560 { 139, 59, 1.169382787 },
5561 { 99, 40, 1.186811703 },
5562 { 211, 81, 1.204257817 },
5563 { 272, 99, 1.221730164 },
5564 { 273, 94, 1.239188479 },
5565 { 277, 90, 1.25664606 },
5566 { 157, 48, 1.274088705 },
5567 { 279, 80, 1.291550147 },
5568 { 362, 97, 1.308990773 },
5569 { 373, 93, 1.326448578 },
5570 { 420, 97, 1.343823596 },
5571 { 207, 44, 1.361353157 },
5572 { 427, 83, 1.378810994 },
5573 { 414, 73, 1.396261926 },
5574 { 322, 51, 1.413716057 },
5575 { 185, 26, 1.431170275 },
5576 { 790, 97, 1.448623034 },
5577 { 333, 35, 1.466075711 },
5578 { 1063, 93, 1.483530284 },
5579 { 1330, 93, 1.500985147 },
5580 { 706, 37, 1.518436297 },
5581 { 315, 11, 1.535889876 },
5582 { 3953, 69, 1.553343002 },
5588 static const QList<rationalTangent> rationalTangents
5590 { 1, 10, qDegreesToRadians( 5.71059 ) },
5591 { 1, 5, qDegreesToRadians( 11.3099 ) },
5592 { 1, 4, qDegreesToRadians( 14.0362 ) },
5593 { 1, 4, qDegreesToRadians( 18.4349 ) },
5594 { 1, 2, qDegreesToRadians( 26.5651 ) },
5595 { 2, 3, qDegreesToRadians( 33.6901 ) },
5596 { 1, 1, qDegreesToRadians( 45.0 ) },
5597 { 3, 2, qDegreesToRadians( 56.3099 ) },
5598 { 2, 1, qDegreesToRadians( 63.4349 ) },
5599 { 3, 1, qDegreesToRadians( 71.5651 ) },
5600 { 4, 1, qDegreesToRadians( 75.9638 ) },
5601 { 10, 1, qDegreesToRadians( 84.2894 ) },
5604 const int quadrant {
static_cast<int>( angleRad / M_PI_2 ) };
5605 Q_ASSERT( quadrant >= 0 && quadrant <= 3 );
5617 angleRad -= M_PI / 2;
5627 angleRad -= M_PI + M_PI_2;
5649 for (
int idx = 0; idx < rationalTangents.count(); ++idx )
5651 const auto item = rationalTangents.at( idx );
5652 if (
qgsDoubleNear( item.angle, angleRad, 10E-3 ) || item.angle > angleRad )
5659 const rationalTangent bTan { rationalTangents.at( rTanIdx ) };
5660 angleRad = bTan.angle;
5661 const double k { bTan.q *height *width / std::cos( angleRad ) };
5662 const int hcfH { std::gcd( bTan.p * height, bTan.q * width ) };
5663 const int hcfW { std::gcd( bTan.q * height, bTan.p * width ) };
5664 const int W1 {
static_cast<int>( std::round( k / hcfW ) ) };
5665 const int H1 {
static_cast<int>( std::round( k / hcfH ) ) };
5678 angleRad += M_PI / 2;
5691 angleRad += M_PI + M_PI_2;
5702template <
typename Functor>
5705 sl->
setId( generateId() );
5713template <
typename Functor>
5747 maskSl->clearMasks();
5750 if (
QgsSymbol *subSymbol = maskSl->subSymbol() )
5761 if ( clipGeometries.empty() )
5764 if ( bounds.isNull() )
5765 return clipGeometries;
5769 clipGeometries.erase(
5770 std::remove_if( clipGeometries.begin(), clipGeometries.end(), [&boundsRect](
const QgsGeometry & geometry )
5772 return !geometry.boundingBoxIntersects( boundsRect );
5773 } ), clipGeometries.end() );
5775 return clipGeometries;
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.
void setForceVectorOutput(bool force)
Sets whether rendering operations should use vector operations instead of any faster raster shortcuts...
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
void 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 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 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 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 bool hasExternalGraphicV2(QDomElement &element, const QString format=QString())
Checks if element contains an ExternalGraphic element, if the optional format is specified it will al...
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 bool needSvgMarker(QDomElement &element)
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 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.