51#include <QDomDocument>
61#include <QRegularExpression>
64#define POINTS_TO_MM 2.83464567
68 return QStringLiteral(
"%1,%2,%3,%4" ).arg( color.red() ).arg( color.green() ).arg( color.blue() ).arg( color.alpha() );
73 const QStringList lst = str.split(
',' );
74 if ( lst.count() < 3 )
78 int red, green, blue, alpha;
80 green = lst[1].toInt();
81 blue = lst[2].toInt();
83 if ( lst.count() > 3 )
85 alpha = lst[3].toInt();
87 return QColor( red, green, blue, alpha );
92 return QString::number( alpha / 255.0,
'g', 2 );
98 double alpha = str.toDouble( &ok );
99 if ( !ok || alpha > 1 )
101 else if ( alpha < 0 )
110 case QFont::StyleNormal:
111 return QStringLiteral(
"normal" );
112 case QFont::StyleItalic:
113 return QStringLiteral(
"italic" );
114 case QFont::StyleOblique:
115 return QStringLiteral(
"oblique" );
123 if ( str == QLatin1String(
"normal" ) )
return QFont::StyleNormal;
124 if ( str == QLatin1String(
"italic" ) )
return QFont::StyleItalic;
125 if ( str == QLatin1String(
"oblique" ) )
return QFont::StyleOblique;
126 return QFont::StyleNormal;
131 if ( weight == 50 )
return QStringLiteral(
"normal" );
132 if ( weight == 75 )
return QStringLiteral(
"bold" );
136 if ( weight < 0 )
return QStringLiteral(
"100" );
137 if ( weight > 99 )
return QStringLiteral(
"900" );
138 return QString::number( weight * 800 / 99 + 100 );
144 const int weight = str.toInt( &ok );
146 return static_cast< int >( QFont::Normal );
150 if ( weight > 900 )
return 99;
151 if ( weight < 100 )
return 0;
152 return ( weight - 100 ) * 99 / 800;
160 return QStringLiteral(
"no" );
162 return QStringLiteral(
"solid" );
164 return QStringLiteral(
"dash" );
166 return QStringLiteral(
"dot" );
167 case Qt::DashDotLine:
168 return QStringLiteral(
"dash dot" );
169 case Qt::DashDotDotLine:
170 return QStringLiteral(
"dash dot dot" );
172 return QStringLiteral(
"???" );
178 if ( str == QLatin1String(
"no" ) )
return Qt::NoPen;
179 if ( str == QLatin1String(
"solid" ) )
return Qt::SolidLine;
180 if ( str == QLatin1String(
"dash" ) )
return Qt::DashLine;
181 if ( str == QLatin1String(
"dot" ) )
return Qt::DotLine;
182 if ( str == QLatin1String(
"dash dot" ) )
return Qt::DashDotLine;
183 if ( str == QLatin1String(
"dash dot dot" ) )
return Qt::DashDotDotLine;
184 return Qt::SolidLine;
192 return QStringLiteral(
"bevel" );
194 return QStringLiteral(
"miter" );
196 return QStringLiteral(
"round" );
198 return QStringLiteral(
"???" );
204 const QString cleaned = str.toLower().trimmed();
205 if ( cleaned == QLatin1String(
"bevel" ) )
206 return Qt::BevelJoin;
207 if ( cleaned == QLatin1String(
"miter" ) )
208 return Qt::MiterJoin;
209 if ( cleaned == QLatin1String(
"round" ) )
210 return Qt::RoundJoin;
211 return Qt::BevelJoin;
219 return QStringLiteral(
"bevel" );
221 return QStringLiteral(
"mitre" );
223 return QStringLiteral(
"round" );
231 if ( str == QLatin1String(
"bevel" ) )
return Qt::BevelJoin;
232 if ( str == QLatin1String(
"mitre" ) )
return Qt::MiterJoin;
233 if ( str == QLatin1String(
"round" ) )
return Qt::RoundJoin;
234 return Qt::BevelJoin;
242 return QStringLiteral(
"square" );
244 return QStringLiteral(
"flat" );
246 return QStringLiteral(
"round" );
248 return QStringLiteral(
"???" );
254 if ( str == QLatin1String(
"square" ) )
return Qt::SquareCap;
255 if ( str == QLatin1String(
"flat" ) )
return Qt::FlatCap;
256 if ( str == QLatin1String(
"round" ) )
return Qt::RoundCap;
257 return Qt::SquareCap;
265 return QStringLiteral(
"square" );
267 return QStringLiteral(
"butt" );
269 return QStringLiteral(
"round" );
277 if ( str == QLatin1String(
"square" ) )
return Qt::SquareCap;
278 if ( str == QLatin1String(
"butt" ) )
return Qt::FlatCap;
279 if ( str == QLatin1String(
"round" ) )
return Qt::RoundCap;
280 return Qt::SquareCap;
287 case Qt::SolidPattern :
288 return QStringLiteral(
"solid" );
289 case Qt::HorPattern :
290 return QStringLiteral(
"horizontal" );
291 case Qt::VerPattern :
292 return QStringLiteral(
"vertical" );
293 case Qt::CrossPattern :
294 return QStringLiteral(
"cross" );
295 case Qt::BDiagPattern :
296 return QStringLiteral(
"b_diagonal" );
297 case Qt::FDiagPattern :
298 return QStringLiteral(
"f_diagonal" );
299 case Qt::DiagCrossPattern :
300 return QStringLiteral(
"diagonal_x" );
301 case Qt::Dense1Pattern :
302 return QStringLiteral(
"dense1" );
303 case Qt::Dense2Pattern :
304 return QStringLiteral(
"dense2" );
305 case Qt::Dense3Pattern :
306 return QStringLiteral(
"dense3" );
307 case Qt::Dense4Pattern :
308 return QStringLiteral(
"dense4" );
309 case Qt::Dense5Pattern :
310 return QStringLiteral(
"dense5" );
311 case Qt::Dense6Pattern :
312 return QStringLiteral(
"dense6" );
313 case Qt::Dense7Pattern :
314 return QStringLiteral(
"dense7" );
316 return QStringLiteral(
"no" );
318 return QStringLiteral(
"???" );
324 if ( str == QLatin1String(
"solid" ) )
return Qt::SolidPattern;
325 if ( str == QLatin1String(
"horizontal" ) )
return Qt::HorPattern;
326 if ( str == QLatin1String(
"vertical" ) )
return Qt::VerPattern;
327 if ( str == QLatin1String(
"cross" ) )
return Qt::CrossPattern;
328 if ( str == QLatin1String(
"b_diagonal" ) )
return Qt::BDiagPattern;
329 if ( str == QLatin1String(
"f_diagonal" ) )
return Qt::FDiagPattern;
330 if ( str == QLatin1String(
"diagonal_x" ) )
return Qt::DiagCrossPattern;
331 if ( str == QLatin1String(
"dense1" ) )
return Qt::Dense1Pattern;
332 if ( str == QLatin1String(
"dense2" ) )
return Qt::Dense2Pattern;
333 if ( str == QLatin1String(
"dense3" ) )
return Qt::Dense3Pattern;
334 if ( str == QLatin1String(
"dense4" ) )
return Qt::Dense4Pattern;
335 if ( str == QLatin1String(
"dense5" ) )
return Qt::Dense5Pattern;
336 if ( str == QLatin1String(
"dense6" ) )
return Qt::Dense6Pattern;
337 if ( str == QLatin1String(
"dense7" ) )
return Qt::Dense7Pattern;
338 if ( str == QLatin1String(
"no" ) )
return Qt::NoBrush;
339 return Qt::SolidPattern;
346 case Qt::CrossPattern:
347 return QStringLiteral(
"cross" );
348 case Qt::DiagCrossPattern:
349 return QStringLiteral(
"x" );
356 return QStringLiteral(
"horline" );
358 return QStringLiteral(
"line" );
359 case Qt::BDiagPattern:
360 return QStringLiteral(
"slash" );
361 case Qt::FDiagPattern:
362 return QStringLiteral(
"backslash" );
365 case Qt::Dense1Pattern:
366 case Qt::Dense2Pattern:
367 case Qt::Dense3Pattern:
368 case Qt::Dense4Pattern:
369 case Qt::Dense5Pattern:
370 case Qt::Dense6Pattern:
371 case Qt::Dense7Pattern:
381 if ( str == QLatin1String(
"horline" ) )
return Qt::HorPattern;
382 if ( str == QLatin1String(
"line" ) )
return Qt::VerPattern;
383 if ( str == QLatin1String(
"cross" ) )
return Qt::CrossPattern;
384 if ( str == QLatin1String(
"slash" ) )
return Qt::BDiagPattern;
385 if ( str == QLatin1String(
"backshash" ) )
return Qt::FDiagPattern;
386 if ( str == QLatin1String(
"x" ) )
return Qt::DiagCrossPattern;
388 if ( str.startsWith( QLatin1String(
"brush://" ) ) )
396 const QDomNodeList children = element.childNodes();
397 for (
int i = 0; i < children.size(); ++i )
399 const QDomElement childElement = children.at( i ).toElement();
400 if ( childElement.tagName() == QLatin1String(
"se:LineSymbolizer" )
401 || childElement.tagName() == QLatin1String(
"se:PointSymbolizer" )
402 || childElement.tagName() == QLatin1String(
"se:PolygonSymbolizer" ) )
410 const QString compareString =
string.trimmed();
414 if ( compareString.compare( QLatin1String(
"feature" ), Qt::CaseInsensitive ) == 0 )
416 else if ( compareString.compare( QLatin1String(
"viewport" ), Qt::CaseInsensitive ) == 0 )
426 switch ( coordinateReference )
429 return QStringLiteral(
"feature" );
431 return QStringLiteral(
"viewport" );
442 const QString s = value.toString().toLower().trimmed();
443 if ( s == QLatin1String(
"single" ) )
445 else if ( s == QLatin1String(
"reversed" ) )
447 else if ( s == QLatin1String(
"double" ) )
449 else if ( value.toInt() == 1 )
451 else if ( value.toInt() == 2 )
453 else if ( value.toInt( &intOk ) == 0 && intOk )
467 const QString s = value.toString().toLower().trimmed();
468 if ( s == QLatin1String(
"plain" ) )
470 else if ( s == QLatin1String(
"lefthalf" ) )
472 else if ( s == QLatin1String(
"righthalf" ) )
474 else if ( value.toInt() == 1 )
476 else if ( value.toInt() == 2 )
478 else if ( value.toInt( &intOk ) == 0 && intOk )
488 const QString compareString =
string.trimmed();
492 if ( compareString.compare( QLatin1String(
"no" ), Qt::CaseInsensitive ) == 0 )
494 else if ( compareString.compare( QLatin1String(
"shape" ), Qt::CaseInsensitive ) == 0 )
496 else if ( compareString.compare( QLatin1String(
"centroid_within" ), Qt::CaseInsensitive ) == 0 )
498 else if ( compareString.compare( QLatin1String(
"completely_within" ), Qt::CaseInsensitive ) == 0 )
511 return QStringLiteral(
"no" );
513 return QStringLiteral(
"shape" );
515 return QStringLiteral(
"centroid_within" );
517 return QStringLiteral(
"completely_within" );
524 const QString compareString =
string.trimmed();
528 if ( compareString.compare( QLatin1String(
"no" ), Qt::CaseInsensitive ) == 0 )
530 else if ( compareString.compare( QLatin1String(
"during_render" ), Qt::CaseInsensitive ) == 0 )
532 else if ( compareString.compare( QLatin1String(
"before_render" ), Qt::CaseInsensitive ) == 0 )
545 return QStringLiteral(
"no" );
547 return QStringLiteral(
"during_render" );
549 return QStringLiteral(
"before_render" );
561 QStringList lst = str.split(
',' );
562 if ( lst.count() != 2 )
563 return QPointF( 0, 0 );
564 return QPointF( lst[0].toDouble(), lst[1].toDouble() );
575 if ( value.userType() == QMetaType::Type::QVariantList )
577 const QVariantList list = value.toList();
578 if ( list.size() != 2 )
582 bool convertOk =
false;
583 const double x = list.at( 0 ).toDouble( &convertOk );
586 const double y = list.at( 1 ).toDouble( &convertOk );
591 return QPointF( x, y );
599 const QStringList list = value.toString().trimmed().split(
',' );
600 if ( list.count() != 2 )
602 bool convertOk =
false;
603 const double x = list.at( 0 ).toDouble( &convertOk );
606 const double y = list.at( 1 ).toDouble( &convertOk );
611 return QPointF( x, y );
625 QStringList lst =
string.split(
',' );
626 if ( lst.count() != 2 )
627 return QSizeF( 0, 0 );
628 return QSizeF( lst[0].toDouble(), lst[1].toDouble() );
639 if ( value.userType() == QMetaType::Type::QVariantList )
641 const QVariantList list = value.toList();
642 if ( list.size() != 2 )
646 bool convertOk =
false;
647 const double x = list.at( 0 ).toDouble( &convertOk );
650 const double y = list.at( 1 ).toDouble( &convertOk );
655 return QSizeF( x, y );
663 const QStringList list = value.toString().trimmed().split(
',' );
664 if ( list.count() != 2 )
666 bool convertOk =
false;
667 const double x = list.at( 0 ).toDouble( &convertOk );
670 const double y = list.at( 1 ).toDouble( &convertOk );
675 return QSizeF( x, y );
696 if ( str.startsWith( QLatin1String(
"3x:" ) ) )
699 const QString chopped = str.mid( 3 );
700 lst = chopped.split(
',' );
704 lst = str.split(
',' );
706 if ( lst.count() < 2 )
709 double minScale = lst[0].toDouble();
711 minScale = minScale != 0 ? 1.0 / minScale : 0;
712 double maxScale = lst[1].toDouble();
714 maxScale = maxScale != 0 ? 1.0 / maxScale : 0;
716 if ( lst.count() < 6 )
736 *scaleFactor = 0.001;
737 return QStringLiteral(
"http://www.opengeospatial.org/se/units/metre" );
742 return QStringLiteral(
"http://www.opengeospatial.org/se/units/metre" );
749 *scaleFactor = 1 / 0.28;
758 if ( str == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
764 else if ( str == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
767 *scaleFactor = 0.3048;
782 QString vectorString;
783 QVector<qreal>::const_iterator it = v.constBegin();
784 for ( ; it != v.constEnd(); ++it )
786 if ( it != v.constBegin() )
788 vectorString.append(
';' );
790 vectorString.append( QString::number( *it ) );
797 QVector<qreal> resultVector;
799 const QStringList realList = s.split(
';' );
800 QStringList::const_iterator it = realList.constBegin();
801 for ( ; it != realList.constEnd(); ++it )
803 resultVector.append( it->toDouble() );
811 QString vectorString;
812 QVector<qreal>::const_iterator it = v.constBegin();
813 for ( ; it != v.constEnd(); ++it )
815 if ( it != v.constBegin() )
817 vectorString.append(
' ' );
819 vectorString.append( QString::number( *it ) );
826 QVector<qreal> resultVector;
828 const QStringList realList = s.split(
' ' );
829 QStringList::const_iterator it = realList.constBegin();
830 for ( ; it != realList.constEnd(); ++it )
832 resultVector.append( it->toDouble() );
840 QString encodedValue;
842 switch ( scaleMethod )
845 encodedValue = QStringLiteral(
"diameter" );
848 encodedValue = QStringLiteral(
"area" );
858 if ( str == QLatin1String(
"diameter" ) )
872 if ( s.compare( QLatin1String(
"Lighten" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Lighten;
873 if ( s.compare( QLatin1String(
"Screen" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Screen;
874 if ( s.compare( QLatin1String(
"Dodge" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorDodge;
875 if ( s.compare( QLatin1String(
"Addition" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Plus;
876 if ( s.compare( QLatin1String(
"Darken" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Darken;
877 if ( s.compare( QLatin1String(
"Multiply" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Multiply;
878 if ( s.compare( QLatin1String(
"Burn" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorBurn;
879 if ( s.compare( QLatin1String(
"Overlay" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Overlay;
880 if ( s.compare( QLatin1String(
"SoftLight" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_SoftLight;
881 if ( s.compare( QLatin1String(
"HardLight" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_HardLight;
882 if ( s.compare( QLatin1String(
"Difference" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Difference;
883 if ( s.compare( QLatin1String(
"Subtract" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Exclusion;
884 return QPainter::CompositionMode_SourceOver;
889 return QIcon(
symbolPreviewPixmap( symbol, size, padding,
nullptr,
false,
nullptr, shape, screen ) );
897 QPixmap pixmap( size * devicePixelRatio );
898 pixmap.setDevicePixelRatio( devicePixelRatio );
900 pixmap.fill( Qt::transparent );
902 painter.begin( &pixmap );
907 painter.setRenderHint( QPainter::Antialiasing );
908 painter.setRenderHint( QPainter::SmoothPixmapTransform );
918 size.setWidth( size.rwidth() - ( padding * 2 ) );
919 size.setHeight( size.rheight() - ( padding * 2 ) );
920 painter.translate( padding, padding );
930 std::unique_ptr<QgsSymbol> symbol_noDD( symbol->
clone( ) );
932 for (
const auto &layer : layers )
934 for (
int i = 0; i < layer->dataDefinedProperties().count(); ++i )
936 QgsProperty &prop = layer->dataDefinedProperties().property( i );
942 symbol_noDD->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape, screen );
946 std::unique_ptr<QgsSymbol> symbolClone( symbol->
clone( ) );
947 symbolClone->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape, screen );
961 maxBleed = layerMaxBleed > maxBleed ? layerMaxBleed : maxBleed;
971 painter.begin( &picture );
972 painter.setRenderHint( QPainter::Antialiasing );
982 switch ( parentSymbolType )
997 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
998 layerClone->drawPreviewIcon( symbolContext, size );
1006 QPixmap pixmap( size * devicePixelRatio );
1007 pixmap.setDevicePixelRatio( devicePixelRatio );
1008 pixmap.fill( Qt::transparent );
1010 painter.begin( &pixmap );
1011 painter.setRenderHint( QPainter::Antialiasing );
1029 switch ( parentSymbolType )
1044 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
1045 layerClone->drawPreviewIcon( symbolContext, size );
1047 return QIcon( pixmap );
1057 QPixmap pixmap( size );
1058 pixmap.fill( Qt::transparent );
1061 painter.begin( &pixmap );
1064 if ( drawTransparentBackground )
1065 drawStippledBackground( &painter, QRect( padding, padding, size.width() - padding * 2, size.height() - padding * 2 ) );
1069 switch ( direction )
1071 case Qt::Horizontal:
1073 for (
int i = 0; i < size.width(); i++ )
1075 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.width() ) );
1076 painter.setPen( pen );
1077 const int x = flipDirection ? size.width() - i - 1 : i;
1078 painter.drawLine( x, 0 + padding, x, size.height() - 1 - padding );
1085 for (
int i = 0; i < size.height(); i++ )
1087 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.height() ) );
1088 painter.setPen( pen );
1089 const int y = flipDirection ? size.height() - i - 1 : i;
1090 painter.drawLine( 0 + padding, y, size.width() - 1 - padding, y );
1103 uchar pixDataRGB[] = { 255, 255, 255, 255,
1108 const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
1110 const int width = ( rect.width() < rect.height() ) ?
1111 rect.width() / 2.5 : rect.height() / 2.5;
1112 const QPixmap pix = QPixmap::fromImage( img.scaled( width, width ) );
1115 brush.setTexture( pix );
1116 painter->fillRect( rect, brush );
1121 const qreal s = ( markerSize - 1 ) / 2.0;
1126 p.setPen( QColor( 50, 100, 120, 200 ) );
1127 p.setBrush( QColor( 200, 200, 210, 120 ) );
1128 p.drawEllipse( x - s, y - s, s * 2, s * 2 );
1131 p.setPen( QColor( 255, 0, 0 ) );
1132 p.drawLine( x - s, y + s, x + s, y - s );
1133 p.drawLine( x - s, y - s, x + s, y + s );
1145static QPolygonF makeOffsetGeometry(
const QgsPolylineXY &polyline )
1147 int i, pointCount = polyline.count();
1149 QPolygonF resultLine;
1150 resultLine.resize( pointCount );
1154 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1155 resultLine[i] = QPointF( tempPtr->
x(), tempPtr->
y() );
1159static QList<QPolygonF> makeOffsetGeometry(
const QgsPolygonXY &polygon )
1161 QList<QPolygonF> resultGeom;
1162 resultGeom.reserve( polygon.size() );
1163 for (
int ring = 0; ring < polygon.size(); ++ring )
1164 resultGeom.append( makeOffsetGeometry( polygon[ ring ] ) );
1170 QList<QPolygonF> resultLine;
1172 if ( polyline.count() < 2 )
1174 resultLine.append( polyline );
1178 unsigned int i, pointCount = polyline.count();
1181 QPointF *tempPtr = polyline.data();
1182 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1183 tempPolyline[i] =
QgsPointXY( tempPtr->rx(), tempPtr->ry() );
1186 if ( !tempGeometry.
isNull() )
1188 const int quadSegments = 0;
1189 const double miterLimit = 2.0;
1197 if ( !offsetGeom.
isNull() )
1199 tempGeometry = offsetGeom;
1204 resultLine.append( makeOffsetGeometry( line ) );
1209 resultLine.append( makeOffsetGeometry( tempGeometry.
asPolygon() ) );
1215 resultLine.reserve( tempMPolyline.count() );
1216 for (
int part = 0; part < tempMPolyline.count(); ++part )
1218 resultLine.append( makeOffsetGeometry( tempMPolyline[ part ] ) );
1225 resultLine.reserve( tempMPolygon.count() );
1226 for (
int part = 0; part < tempMPolygon.count(); ++part )
1228 resultLine.append( makeOffsetGeometry( tempMPolygon[ part ] ) );
1236 resultLine.append( polyline );
1245 if ( element.isNull() )
1249 QDomNode layerNode = element.firstChild();
1251 while ( !layerNode.isNull() )
1253 QDomElement e = layerNode.toElement();
1254 if ( !e.isNull() && e.tagName() != QLatin1String(
"data_defined_properties" ) && e.tagName() != QLatin1String(
"buffer" ) )
1256 if ( e.tagName() != QLatin1String(
"layer" ) )
1265 const QDomElement s = e.firstChildElement( QStringLiteral(
"symbol" ) );
1268 std::unique_ptr< QgsSymbol > subSymbol(
loadSymbol( s, context ) );
1275 layers.append( layer );
1277 for (
int i = 0; i < subSymbol->symbolLayerCount(); ++i )
1279 layers.append( subSymbol->symbolLayer( i )->clone() );
1284 const bool res = layer->setSubSymbol( subSymbol.release() );
1287 QgsDebugError( QStringLiteral(
"symbol layer refused subsymbol: " ) + s.attribute(
"name" ) );
1289 layers.append( layer );
1294 layers.append( layer );
1299 layerNode = layerNode.nextSibling();
1302 if ( layers.isEmpty() )
1308 const QString symbolType = element.attribute( QStringLiteral(
"type" ) );
1311 if ( symbolType == QLatin1String(
"line" ) )
1313 else if ( symbolType == QLatin1String(
"fill" ) )
1315 else if ( symbolType == QLatin1String(
"marker" ) )
1323 if ( element.hasAttribute( QStringLiteral(
"outputUnit" ) ) )
1327 if ( element.hasAttribute( ( QStringLiteral(
"mapUnitScale" ) ) ) )
1330 const double oldMin = element.attribute( QStringLiteral(
"mapUnitMinScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1331 mapUnitScale.
minScale = oldMin != 0 ? 1.0 / oldMin : 0;
1332 const double oldMax = element.attribute( QStringLiteral(
"mapUnitMaxScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1333 mapUnitScale.
maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
1336 symbol->
setOpacity( element.attribute( QStringLiteral(
"alpha" ), QStringLiteral(
"1.0" ) ).toDouble() );
1337 symbol->
setExtentBuffer( element.attribute( QStringLiteral(
"extent_buffer" ), QStringLiteral(
"0.0" ) ).toDouble() );
1339 symbol->
setClipFeaturesToExtent( element.attribute( QStringLiteral(
"clip_to_extent" ), QStringLiteral(
"1" ) ).toInt() );
1340 symbol->
setForceRHR( element.attribute( QStringLiteral(
"force_rhr" ), QStringLiteral(
"0" ) ).toInt() );
1342 if ( element.attribute( QStringLiteral(
"renderer_should_use_levels" ), QStringLiteral(
"0" ) ).toInt() )
1349 if ( !element.firstChildElement( QStringLiteral(
"buffer" ) ).isNull() )
1351 std::unique_ptr< QgsSymbolBufferSettings > bufferSettings = std::make_unique< QgsSymbolBufferSettings >();
1352 bufferSettings->readXml( element, context );
1360 const QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1361 if ( !ddProps.isNull() )
1371 const QString layerClass = element.attribute( QStringLiteral(
"class" ) );
1372 const bool locked = element.attribute( QStringLiteral(
"locked" ) ).toInt();
1373 const bool enabled = element.attribute( QStringLiteral(
"enabled" ), QStringLiteral(
"1" ) ).toInt();
1374 const int pass = element.attribute( QStringLiteral(
"pass" ) ).toInt();
1375 const QString
id = element.attribute( QStringLiteral(
"id" ) );
1396 if ( !
id.isEmpty() )
1400 const QDomElement effectElem = element.firstChildElement( QStringLiteral(
"effect" ) );
1401 if ( !effectElem.isNull() )
1409 const QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1410 if ( !ddProps.isNull() )
1417 const QSet< int > oldKeys = prevProperties.
propertyKeys();
1418 for (
int key : oldKeys )
1439 return QStringLiteral(
"line" );
1441 return QStringLiteral(
"marker" );
1443 return QStringLiteral(
"fill" );
1452 QDomElement symEl = doc.createElement( QStringLiteral(
"symbol" ) );
1453 symEl.setAttribute( QStringLiteral(
"type" ), _nameForSymbolType( symbol->
type() ) );
1454 symEl.setAttribute( QStringLiteral(
"name" ), name );
1455 symEl.setAttribute( QStringLiteral(
"alpha" ), QString::number( symbol->
opacity() ) );
1456 symEl.setAttribute( QStringLiteral(
"clip_to_extent" ), symbol->
clipFeaturesToExtent() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1459 symEl.setAttribute( QStringLiteral(
"extent_buffer" ), QString::number( symbol->
extentBuffer() ) );
1462 symEl.setAttribute( QStringLiteral(
"force_rhr" ), symbol->
forceRHR() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1464 symEl.setAttribute( QStringLiteral(
"renderer_should_use_levels" ), QStringLiteral(
"1" ) );
1466 symEl.setAttribute( QStringLiteral(
"is_animated" ), symbol->
animationSettings().
isAnimated() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1470 bufferSettings->writeXml( symEl, context );
1474 QDomElement ddProps = doc.createElement( QStringLiteral(
"data_defined_properties" ) );
1476 symEl.appendChild( ddProps );
1482 QDomElement layerEl = doc.createElement( QStringLiteral(
"layer" ) );
1483 layerEl.setAttribute( QStringLiteral(
"class" ), layer->
layerType() );
1484 layerEl.setAttribute( QStringLiteral(
"enabled" ), layer->
enabled() );
1485 layerEl.setAttribute( QStringLiteral(
"locked" ), layer->
isLocked() );
1486 layerEl.setAttribute( QStringLiteral(
"pass" ), layer->
renderingPass() );
1487 layerEl.setAttribute( QStringLiteral(
"id" ), layer->
id() );
1501 QDomElement ddProps = doc.createElement( QStringLiteral(
"data_defined_properties" ) );
1503 layerEl.appendChild( ddProps );
1507 const QString subname = QStringLiteral(
"@%1@%2" ).arg( name ).arg( i );
1508 const QDomElement subEl =
saveSymbol( subname, subSymbol, doc, context );
1509 layerEl.appendChild( subEl );
1511 symEl.appendChild( layerEl );
1519 QDomDocument doc( QStringLiteral(
"qgis-symbol-definition" ) );
1522 QTextStream stream( &props );
1523 symbolElem.save( stream, -1 );
1529 QList<QgsSymbolLayer *> &layers )
1533 if ( element.isNull() )
1538 const QString symbolizerName = element.localName();
1540 if ( symbolizerName == QLatin1String(
"PointSymbolizer" ) )
1543 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1544 if ( graphicElem.isNull() )
1546 QgsDebugError( QStringLiteral(
"Graphic element not found in PointSymbolizer" ) );
1582 if ( symbolizerName == QLatin1String(
"LineSymbolizer" ) )
1585 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1586 if ( strokeElem.isNull() )
1588 QgsDebugError( QStringLiteral(
"Stroke element not found in LineSymbolizer" ) );
1618 if ( symbolizerName == QLatin1String(
"PolygonSymbolizer" ) )
1621 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1622 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1623 if ( fillElem.isNull() && strokeElem.isNull() )
1625 QgsDebugError( QStringLiteral(
"neither Fill nor Stroke element not found in PolygonSymbolizer" ) );
1643 if ( l->
layerType() == QLatin1String(
"SimpleFill" ) || l->
layerType() == QLatin1String(
"SVGFill" ) )
1679 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1680 if ( fillElem.isNull() )
1682 QgsDebugError( QStringLiteral(
"Fill element not found" ) );
1704 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1705 if ( strokeElem.isNull() )
1707 QgsDebugError( QStringLiteral(
"Stroke element not found" ) );
1723 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1724 if ( graphicElem.isNull() )
1726 QgsDebugError( QStringLiteral(
"Graphic element not found" ) );
1751 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1752 if ( graphicElem.isNull() )
1755 const QDomElement externalGraphicElem = graphicElem.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
1756 if ( externalGraphicElem.isNull() )
1760 const QDomElement formatElem = externalGraphicElem.firstChildElement( QStringLiteral(
"Format" ) );
1761 if ( formatElem.isNull() )
1764 const QString elementFormat = formatElem.firstChild().nodeValue();
1765 if ( ! format.isEmpty() && elementFormat != format )
1767 QgsDebugMsgLevel(
"unsupported External Graphic format found: " + elementFormat, 4 );
1772 const QDomElement onlineResourceElem = externalGraphicElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1773 const QDomElement inlineContentElem = externalGraphicElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1774 if ( !onlineResourceElem.isNull() )
1779 else if ( !inlineContentElem.isNull() )
1792 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1793 if ( graphicElem.isNull() )
1796 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1797 if ( markElem.isNull() )
1800 const QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
1801 return !wellKnownNameElem.isNull();
1807 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1808 if ( graphicElem.isNull() )
1811 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1812 if ( markElem.isNull() )
1816 const QDomElement formatElem = markElem.firstChildElement( QStringLiteral(
"Format" ) );
1817 if ( formatElem.isNull() )
1820 const QString format = formatElem.firstChild().nodeValue();
1821 if ( format != QLatin1String(
"ttf" ) )
1823 QgsDebugError(
"unsupported Graphic Mark format found: " + format );
1828 const QDomElement onlineResourceElem = markElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1829 const QDomElement inlineContentElem = markElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1830 if ( !onlineResourceElem.isNull() )
1833 const QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
1834 if ( !markIndexElem.isNull() )
1837 else if ( !inlineContentElem.isNull() )
1852 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1853 if ( graphicElem.isNull() )
1857 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
1859 if ( it.key() == QLatin1String(
"widthHeightFactor" ) )
1870 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1871 if ( strokeElem.isNull() )
1874 QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral(
"GraphicStroke" ) );
1875 if ( graphicStrokeElem.isNull() )
1883 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1884 if ( fillElem.isNull() )
1887 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1888 if ( graphicFillElem.isNull() )
1891 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1892 if ( graphicElem.isNull() )
1898 QColor fillColor, strokeColor;
1899 double size, strokeWidth;
1900 Qt::PenStyle strokeStyle;
1901 if ( !
wellKnownMarkerFromSld( graphicElem, name, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
1904 if ( name != QLatin1String(
"horline" ) )
1912 const double angle = angleFunc.toDouble( &ok );
1918 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1919 if ( fillElem.isNull() )
1922 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1923 if ( graphicFillElem.isNull() )
1926 const QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1927 if ( graphicElem.isNull() )
1930 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1931 if ( markElem.isNull() )
1939 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1940 if ( fillElem.isNull() )
1943 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1944 if ( graphicFillElem.isNull() )
1952 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1953 if ( fillElem.isNull() )
1956 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1957 if ( graphicFillElem.isNull() )
1977 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1978 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1982 bool validFill =
false, validStroke =
false;
1987 Qt::BrushStyle fillStyle;
1989 if (
fillFromSld( fillElem, fillStyle, fillColor ) )
1995 Qt::PenStyle strokeStyle;
1996 double strokeWidth = 1.0, dashOffset = 0.0;
1997 QVector<qreal> customDashPattern;
1999 if (
lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth,
2000 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2003 if ( validFill || validStroke )
2006 map[QStringLiteral(
"name" )] = QStringLiteral(
"square" );
2009 map[QStringLiteral(
"size" )] = QString::number( 6 );
2010 map[QStringLiteral(
"angle" )] = QString::number( 0 );
2011 map[QStringLiteral(
"offset" )] =
encodePoint( QPointF( 0, 0 ) );
2018 bool validFill =
false, validStroke =
false;
2021 QString name, format;
2023 QColor fillColor, strokeColor;
2024 double strokeWidth = 1.0, size = 0.0, angle = 0.0;
2028 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
2029 if ( !graphicFillElem.isNull() )
2032 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
2033 if ( !graphicElem.isNull() )
2039 const QDomElement graphicChildElem = graphicElem.firstChildElement();
2040 while ( !graphicChildElem.isNull() )
2042 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2045 const QDomElement wellKnownNameElem = graphicChildElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
2046 if ( !wellKnownNameElem.isNull() )
2048 name = wellKnownNameElem.firstChild().nodeValue();
2054 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) || graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2057 const QDomElement formatElem = graphicChildElem.firstChildElement( QStringLiteral(
"Format" ) );
2058 if ( formatElem.isNull() )
2061 format = formatElem.firstChild().nodeValue();
2065 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) && format != QLatin1String(
"image/svg+xml" ) )
2070 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format != QLatin1String(
"ttf" ) )
2074 const QDomElement onlineResourceElem = graphicChildElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
2075 const QDomElement inlineContentElem = graphicChildElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
2077 if ( !onlineResourceElem.isNull() )
2079 name = onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) );
2081 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format == QLatin1String(
"ttf" ) )
2084 if ( name.startsWith( QLatin1String(
"ttf://" ) ) )
2085 name = name.mid( 6 );
2088 const QDomElement markIndexElem = graphicChildElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
2089 if ( markIndexElem.isNull() )
2093 const int v = markIndexElem.firstChild().nodeValue().toInt( &ok );
2104 else if ( !inlineContentElem.isNull() )
2114 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2116 name = QStringLiteral(
"square" );
2123 if ( found && graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2130 Qt::BrushStyle markFillStyle;
2132 QDomElement markFillElem = graphicChildElem.firstChildElement( QStringLiteral(
"Fill" ) );
2133 if (
fillFromSld( markFillElem, markFillStyle, fillColor ) )
2138 Qt::PenStyle strokeStyle;
2139 double strokeWidth = 1.0, dashOffset = 0.0;
2140 QVector<qreal> customDashPattern;
2142 QDomElement markStrokeElem = graphicChildElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2143 if (
lineFromSld( markStrokeElem, strokeStyle, strokeColor, strokeWidth,
2144 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2151 const QDomElement opacityElem = graphicElem.firstChildElement( QStringLiteral(
"Opacity" ) );
2152 if ( !opacityElem.isNull() )
2153 fillColor.setAlpha(
decodeSldAlpha( opacityElem.firstChild().nodeValue() ) );
2155 const QDomElement sizeElem = graphicElem.firstChildElement( QStringLiteral(
"Size" ) );
2156 if ( !sizeElem.isNull() )
2159 const double v = sizeElem.firstChild().nodeValue().toDouble( &ok );
2168 const double v = angleFunc.toDouble( &ok );
2178 if ( validFill || validStroke )
2180 if ( format == QLatin1String(
"image/svg+xml" ) )
2183 map[QStringLiteral(
"name" )] = name;
2184 map[QStringLiteral(
"fill" )] = fillColor.name();
2185 map[QStringLiteral(
"outline" )] = strokeColor.name();
2186 map[QStringLiteral(
"outline-width" )] = QString::number( strokeWidth );
2188 map[QStringLiteral(
"size" )] = QString::number( size );
2190 map[QStringLiteral(
"angle" )] = QString::number( angle );
2191 if ( !offset.isNull() )
2192 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
2195 else if ( format == QLatin1String(
"ttf" ) )
2198 map[QStringLiteral(
"font" )] = name;
2199 map[QStringLiteral(
"chr" )] = markIndex;
2202 map[QStringLiteral(
"size" )] = QString::number( size );
2204 map[QStringLiteral(
"angle" )] = QString::number( angle );
2205 if ( !offset.isNull() )
2206 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
2212 if ( layers.isEmpty() )
2215 layerList << layers;
2222 QString patternName;
2223 switch ( brushStyle )
2228 case Qt::SolidPattern:
2229 if ( color.isValid() )
2232 if ( color.alpha() < 255 )
2237 case Qt::CrossPattern:
2238 case Qt::DiagCrossPattern:
2239 case Qt::HorPattern:
2240 case Qt::VerPattern:
2241 case Qt::BDiagPattern:
2242 case Qt::FDiagPattern:
2243 case Qt::Dense1Pattern:
2244 case Qt::Dense2Pattern:
2245 case Qt::Dense3Pattern:
2246 case Qt::Dense4Pattern:
2247 case Qt::Dense5Pattern:
2248 case Qt::Dense6Pattern:
2249 case Qt::Dense7Pattern:
2254 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( brushStyle ) ) );
2258 QDomElement graphicFillElem = doc.createElement( QStringLiteral(
"se:GraphicFill" ) );
2259 element.appendChild( graphicFillElem );
2261 QDomElement graphicElem = doc.createElement( QStringLiteral(
"se:Graphic" ) );
2262 graphicFillElem.appendChild( graphicElem );
2264 const QColor fillColor = patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
2265 const QColor strokeColor = !patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
2268 wellKnownMarkerToSld( doc, graphicElem, patternName, fillColor, strokeColor, Qt::SolidLine, -1, -1 );
2275 brushStyle = Qt::SolidPattern;
2276 color = QColor( 128, 128, 128 );
2278 if ( element.isNull() )
2280 brushStyle = Qt::NoBrush;
2285 const QDomElement graphicFillElem = element.firstChildElement( QStringLiteral(
"GraphicFill" ) );
2287 if ( graphicFillElem.isNull() )
2290 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2292 QgsDebugMsgLevel( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ), 2 );
2294 if ( it.key() == QLatin1String(
"fill" ) )
2295 color = QColor( it.value() );
2296 else if ( it.key() == QLatin1String(
"fill-opacity" ) )
2302 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
2303 if ( graphicElem.isNull() )
2306 QString patternName = QStringLiteral(
"square" );
2307 QColor fillColor, strokeColor;
2308 double strokeWidth, size;
2309 Qt::PenStyle strokeStyle;
2310 if ( !
wellKnownMarkerFromSld( graphicElem, patternName, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
2314 if ( brushStyle == Qt::NoBrush )
2317 const QColor
c = patternName.startsWith( QLatin1String(
"brush://" ) ) ? fillColor : strokeColor;
2326 Qt::PenStyle penStyle,
const QColor &color,
double width,
2327 const Qt::PenJoinStyle *penJoinStyle,
const Qt::PenCapStyle *penCapStyle,
2328 const QVector<qreal> *customDashPattern,
double dashOffset )
2330 QVector<qreal> dashPattern;
2331 const QVector<qreal> *pattern = &dashPattern;
2333 if ( penStyle == Qt::CustomDashLine && !customDashPattern )
2335 element.appendChild( doc.createComment( QStringLiteral(
"WARNING: Custom dash pattern required but not provided. Using default dash pattern." ) ) );
2336 penStyle = Qt::DashLine;
2348 dashPattern.push_back( 4.0 );
2349 dashPattern.push_back( 2.0 );
2352 dashPattern.push_back( 1.0 );
2353 dashPattern.push_back( 2.0 );
2355 case Qt::DashDotLine:
2356 dashPattern.push_back( 4.0 );
2357 dashPattern.push_back( 2.0 );
2358 dashPattern.push_back( 1.0 );
2359 dashPattern.push_back( 2.0 );
2361 case Qt::DashDotDotLine:
2362 dashPattern.push_back( 4.0 );
2363 dashPattern.push_back( 2.0 );
2364 dashPattern.push_back( 1.0 );
2365 dashPattern.push_back( 2.0 );
2366 dashPattern.push_back( 1.0 );
2367 dashPattern.push_back( 2.0 );
2370 case Qt::CustomDashLine:
2371 Q_ASSERT( customDashPattern );
2372 pattern = customDashPattern;
2376 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( penStyle ) ) );
2380 if ( color.isValid() )
2383 if ( color.alpha() < 255 )
2390 else if ( width == 0 )
2400 if ( !pattern->isEmpty() )
2410 Qt::PenStyle &penStyle, QColor &color,
double &width,
2411 Qt::PenJoinStyle *penJoinStyle, Qt::PenCapStyle *penCapStyle,
2412 QVector<qreal> *customDashPattern,
double *dashOffset )
2416 penStyle = Qt::SolidLine;
2417 color = QColor( 0, 0, 0 );
2420 *penJoinStyle = Qt::BevelJoin;
2422 *penCapStyle = Qt::SquareCap;
2423 if ( customDashPattern )
2424 customDashPattern->clear();
2428 if ( element.isNull() )
2430 penStyle = Qt::NoPen;
2436 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2438 QgsDebugMsgLevel( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ), 2 );
2440 if ( it.key() == QLatin1String(
"stroke" ) )
2442 color = QColor( it.value() );
2444 else if ( it.key() == QLatin1String(
"stroke-opacity" ) )
2448 else if ( it.key() == QLatin1String(
"stroke-width" ) )
2451 const double w = it.value().toDouble( &ok );
2455 else if ( it.key() == QLatin1String(
"stroke-linejoin" ) && penJoinStyle )
2459 else if ( it.key() == QLatin1String(
"stroke-linecap" ) && penCapStyle )
2463 else if ( it.key() == QLatin1String(
"stroke-dasharray" ) )
2466 if ( !dashPattern.isEmpty() )
2470 bool dashPatternFound =
false;
2472 if ( dashPattern.count() == 2 )
2474 if ( dashPattern.at( 0 ) == 4.0 &&
2475 dashPattern.at( 1 ) == 2.0 )
2477 penStyle = Qt::DashLine;
2478 dashPatternFound =
true;
2480 else if ( dashPattern.at( 0 ) == 1.0 &&
2481 dashPattern.at( 1 ) == 2.0 )
2483 penStyle = Qt::DotLine;
2484 dashPatternFound =
true;
2487 else if ( dashPattern.count() == 4 )
2489 if ( dashPattern.at( 0 ) == 4.0 &&
2490 dashPattern.at( 1 ) == 2.0 &&
2491 dashPattern.at( 2 ) == 1.0 &&
2492 dashPattern.at( 3 ) == 2.0 )
2494 penStyle = Qt::DashDotLine;
2495 dashPatternFound =
true;
2498 else if ( dashPattern.count() == 6 )
2500 if ( dashPattern.at( 0 ) == 4.0 &&
2501 dashPattern.at( 1 ) == 2.0 &&
2502 dashPattern.at( 2 ) == 1.0 &&
2503 dashPattern.at( 3 ) == 2.0 &&
2504 dashPattern.at( 4 ) == 1.0 &&
2505 dashPattern.at( 5 ) == 2.0 )
2507 penStyle = Qt::DashDotDotLine;
2508 dashPatternFound =
true;
2513 if ( !dashPatternFound )
2515 if ( customDashPattern )
2517 penStyle = Qt::CustomDashLine;
2518 *customDashPattern = dashPattern;
2522 QgsDebugMsgLevel( QStringLiteral(
"custom dash pattern required but not provided. Using default dash pattern." ), 2 );
2523 penStyle = Qt::DashLine;
2528 else if ( it.key() == QLatin1String(
"stroke-dashoffset" ) && dashOffset )
2531 const double d = it.value().toDouble( &ok );
2541 const QString &path,
const QString &mime,
2542 const QColor &color,
double size )
2544 QDomElement externalGraphicElem = doc.createElement( QStringLiteral(
"se:ExternalGraphic" ) );
2545 element.appendChild( externalGraphicElem );
2554 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2556 element.appendChild( sizeElem );
2561 const QString &path,
const QColor &fillColor,
double size,
const QColor &strokeColor,
double strokeWidth )
2568 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Parametric SVG" ) ) );
2569 const QString parametricPath =
getSvgParametricPath( path, fillColor, strokeColor, strokeWidth );
2572 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Plain SVG fallback, no parameters" ) ) );
2575 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Well known marker fallback" ) ) );
2581 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2583 graphicElem.appendChild( sizeElem );
2591 if ( fillColor.isValid() )
2593 url.addQueryItem( QStringLiteral(
"fill" ), fillColor.name() );
2594 url.addQueryItem( QStringLiteral(
"fill-opacity" ),
encodeSldAlpha( fillColor.alpha() ) );
2598 url.addQueryItem( QStringLiteral(
"fill" ), QStringLiteral(
"#000000" ) );
2599 url.addQueryItem( QStringLiteral(
"fill-opacity" ), QStringLiteral(
"1" ) );
2601 if ( strokeColor.isValid() )
2603 url.addQueryItem( QStringLiteral(
"outline" ), strokeColor.name() );
2604 url.addQueryItem( QStringLiteral(
"outline-opacity" ),
encodeSldAlpha( strokeColor.alpha() ) );
2608 url.addQueryItem( QStringLiteral(
"outline" ), QStringLiteral(
"#000000" ) );
2609 url.addQueryItem( QStringLiteral(
"outline-opacity" ), QStringLiteral(
"1" ) );
2611 url.addQueryItem( QStringLiteral(
"outline-width" ), QString::number( strokeWidth ) );
2612 const QString params = url.toString( QUrl::FullyEncoded );
2613 if ( params.isEmpty() )
2619 return basePath +
"?" + params;
2624 QString &path, QString &mime,
2625 QColor &color,
double &size )
2630 QDomElement externalGraphicElem = element.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
2631 if ( externalGraphicElem.isNull() )
2636 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2637 if ( !sizeElem.isNull() )
2640 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2649 const QString &path,
const QString &format,
int *markIndex,
2650 const QColor &color,
double size )
2652 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2653 element.appendChild( markElem );
2659 QDomElement markIndexElem = doc.createElement( QStringLiteral(
"se:MarkIndex" ) );
2660 markIndexElem.appendChild( doc.createTextNode( QString::number( *markIndex ) ) );
2661 markElem.appendChild( markIndexElem );
2665 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2666 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2667 markElem.appendChild( fillElem );
2672 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2674 element.appendChild( sizeElem );
2679 QString &path, QString &format,
int &markIndex,
2680 QColor &color,
double &size )
2688 QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2689 if ( markElem.isNull() )
2694 const QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
2695 if ( !markIndexElem.isNull() )
2698 const int i = markIndexElem.firstChild().nodeValue().toInt( &ok );
2704 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2705 Qt::BrushStyle b = Qt::SolidPattern;
2710 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2711 if ( !sizeElem.isNull() )
2714 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2723 const QString &name,
const QColor &color,
const QColor &strokeColor, Qt::PenStyle strokeStyle,
2724 double strokeWidth,
double size )
2726 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2727 element.appendChild( markElem );
2729 QDomElement wellKnownNameElem = doc.createElement( QStringLiteral(
"se:WellKnownName" ) );
2730 wellKnownNameElem.appendChild( doc.createTextNode( name ) );
2731 markElem.appendChild( wellKnownNameElem );
2734 if ( color.isValid() )
2736 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2737 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2738 markElem.appendChild( fillElem );
2742 if ( strokeColor.isValid() )
2744 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
2745 lineToSld( doc, strokeElem, strokeStyle, strokeColor, strokeWidth );
2746 markElem.appendChild( strokeElem );
2752 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2754 element.appendChild( sizeElem );
2759 QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle,
2760 double &strokeWidth,
double &size )
2764 name = QStringLiteral(
"square" );
2766 strokeColor = QColor( 0, 0, 0 );
2770 const QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2771 if ( markElem.isNull() )
2774 const QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
2775 if ( !wellKnownNameElem.isNull() )
2777 name = wellKnownNameElem.firstChild().nodeValue();
2782 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2783 Qt::BrushStyle b = Qt::SolidPattern;
2788 QDomElement strokeElem = markElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2789 lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth );
2793 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2794 if ( !sizeElem.isNull() )
2797 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2807 if ( !rotationFunc.isEmpty() )
2809 QDomElement rotationElem = doc.createElement( QStringLiteral(
"se:Rotation" ) );
2811 element.appendChild( rotationElem );
2817 QDomElement rotationElem = element.firstChildElement( QStringLiteral(
"Rotation" ) );
2818 if ( !rotationElem.isNull() )
2828 if ( !alphaFunc.isEmpty() )
2830 QDomElement opacityElem = doc.createElement( QStringLiteral(
"se:Opacity" ) );
2832 element.appendChild( opacityElem );
2838 QDomElement opacityElem = element.firstChildElement( QStringLiteral(
"Opacity" ) );
2839 if ( !opacityElem.isNull() )
2848 if ( offset.isNull() )
2851 QDomElement displacementElem = doc.createElement( QStringLiteral(
"se:Displacement" ) );
2852 element.appendChild( displacementElem );
2854 QDomElement dispXElem = doc.createElement( QStringLiteral(
"se:DisplacementX" ) );
2855 dispXElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.x(), 2 ) ) );
2857 QDomElement dispYElem = doc.createElement( QStringLiteral(
"se:DisplacementY" ) );
2858 dispYElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.y(), 2 ) ) );
2860 displacementElem.appendChild( dispXElem );
2861 displacementElem.appendChild( dispYElem );
2868 QDomElement anchorElem = doc.createElement( QStringLiteral(
"se:AnchorPoint" ) );
2869 element.appendChild( anchorElem );
2871 QDomElement anchorXElem = doc.createElement( QStringLiteral(
"se:AnchorPointX" ) );
2872 anchorXElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.x() ) ) );
2874 QDomElement anchorYElem = doc.createElement( QStringLiteral(
"se:AnchorPointY" ) );
2875 anchorYElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.y() ) ) );
2877 anchorElem.appendChild( anchorXElem );
2878 anchorElem.appendChild( anchorYElem );
2883 offset = QPointF( 0, 0 );
2885 const QDomElement displacementElem = element.firstChildElement( QStringLiteral(
"Displacement" ) );
2886 if ( displacementElem.isNull() )
2889 const QDomElement dispXElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementX" ) );
2890 if ( !dispXElem.isNull() )
2893 const double offsetX = dispXElem.firstChild().nodeValue().toDouble( &ok );
2895 offset.setX( offsetX );
2898 const QDomElement dispYElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementY" ) );
2899 if ( !dispYElem.isNull() )
2902 const double offsetY = dispYElem.firstChild().nodeValue().toDouble( &ok );
2904 offset.setY( offsetY );
2911 const QString &label,
const QFont &font,
2912 const QColor &color,
double size )
2914 QDomElement labelElem = doc.createElement( QStringLiteral(
"se:Label" ) );
2915 labelElem.appendChild( doc.createTextNode( label ) );
2916 element.appendChild( labelElem );
2918 QDomElement fontElem = doc.createElement( QStringLiteral(
"se:Font" ) );
2919 element.appendChild( fontElem );
2923 fontElem.appendChild( createSldParameterElement( doc,
"font-style",
encodeSldFontStyle( font.style() ) ) );
2924 fontElem.appendChild( createSldParameterElement( doc,
"font-weight",
encodeSldFontWeight( font.weight() ) ) );
2929 if ( color.isValid() )
2931 QDomElement fillElem = doc.createElement( QStringLiteral(
"Fill" ) );
2932 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2933 element.appendChild( fillElem );
2938 Qt::PenJoinStyle joinStyle,
2939 Qt::PenCapStyle capStyle,
2941 const QVector<qreal> *dashPattern )
2944 penStyle.append(
"PEN(" );
2945 penStyle.append(
"c:" );
2946 penStyle.append(
c.name() );
2947 penStyle.append(
",w:" );
2949 penStyle.append( QString::number( width * mmScaleFactor ) );
2950 penStyle.append(
"mm" );
2953 if ( dashPattern && !dashPattern->isEmpty() )
2955 penStyle.append(
",p:\"" );
2956 QVector<qreal>::const_iterator pIt = dashPattern->constBegin();
2957 for ( ; pIt != dashPattern->constEnd(); ++pIt )
2959 if ( pIt != dashPattern->constBegin() )
2961 penStyle.append(
' ' );
2963 penStyle.append( QString::number( *pIt * mapUnitScaleFactor ) );
2964 penStyle.append(
'g' );
2966 penStyle.append(
'\"' );
2970 penStyle.append(
",cap:" );
2974 penStyle.append(
'p' );
2977 penStyle.append(
'r' );
2981 penStyle.append(
'b' );
2985 penStyle.append(
",j:" );
2986 switch ( joinStyle )
2989 penStyle.append(
'b' );
2992 penStyle.append(
'r' );
2996 penStyle.append(
'm' );
3002 penStyle.append(
",dp:" );
3003 penStyle.append( QString::number( offset * mapUnitScaleFactor ) );
3004 penStyle.append(
'g' );
3007 penStyle.append(
')' );
3014 brushStyle.append(
"BRUSH(" );
3015 brushStyle.append(
"fc:" );
3016 brushStyle.append( fillColor.name() );
3017 brushStyle.append(
')' );
3023 if ( geomFunc.isEmpty() )
3026 QDomElement geometryElem = doc.createElement( QStringLiteral(
"Geometry" ) );
3027 element.appendChild( geometryElem );
3057 QDomElement geometryElem = element.firstChildElement( QStringLiteral(
"Geometry" ) );
3058 if ( geometryElem.isNull() )
3070 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " + function ) );
3074 if ( !filterElem.isNull() )
3075 element.appendChild( filterElem );
3083 if ( function == QLatin1String(
"ELSE" ) )
3086 element.appendChild( filterElem );
3095 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " + function ) );
3099 if ( !filterElem.isNull() )
3100 element.appendChild( filterElem );
3108 QDomElement elem = element;
3109 if ( element.tagName() != QLatin1String(
"Filter" ) )
3111 const QDomNodeList filterNodes = element.elementsByTagName( QStringLiteral(
"Filter" ) );
3112 if ( !filterNodes.isEmpty() )
3114 elem = filterNodes.at( 0 ).toElement();
3118 if ( elem.isNull() )
3143 const QString &path,
const QString &format )
3147 QDomElement onlineResourceElem = doc.createElement( QStringLiteral(
"se:OnlineResource" ) );
3148 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
3149 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:href" ), url );
3150 element.appendChild( onlineResourceElem );
3152 QDomElement formatElem = doc.createElement( QStringLiteral(
"se:Format" ) );
3153 formatElem.appendChild( doc.createTextNode( format ) );
3154 element.appendChild( formatElem );
3161 const QDomElement onlineResourceElem = element.firstChildElement( QStringLiteral(
"OnlineResource" ) );
3162 if ( onlineResourceElem.isNull() )
3165 path = QUrl::fromPercentEncoding( onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) ).toUtf8() );
3167 const QDomElement formatElem = element.firstChildElement( QStringLiteral(
"Format" ) );
3168 if ( formatElem.isNull() )
3171 format = formatElem.firstChild().nodeValue();
3178 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:SvgParameter" ) );
3179 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
3180 nodeElem.appendChild( doc.createTextNode( value ) );
3189 QDomElement paramElem = element.firstChildElement();
3190 while ( !paramElem.isNull() )
3192 if ( paramElem.localName() == QLatin1String(
"SvgParameter" ) || paramElem.localName() == QLatin1String(
"CssParameter" ) )
3194 const QString name = paramElem.attribute( QStringLiteral(
"name" ) );
3195 if ( paramElem.firstChild().nodeType() == QDomNode::TextNode )
3197 value = paramElem.firstChild().nodeValue();
3201 if ( paramElem.firstChild().nodeType() == QDomNode::ElementNode &&
3202 paramElem.firstChild().localName() == QLatin1String(
"Literal" ) )
3205 value = paramElem.firstChild().firstChild().nodeValue();
3209 QgsDebugError( QStringLiteral(
"unexpected child of %1" ).arg( paramElem.localName() ) );
3213 if ( !name.isEmpty() && !value.isEmpty() )
3214 params[ name ] = value;
3217 paramElem = paramElem.nextSiblingElement();
3225 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:VendorOption" ) );
3226 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
3227 nodeElem.appendChild( doc.createTextNode( value ) );
3235 QDomElement paramElem = element.firstChildElement( QStringLiteral(
"VendorOption" ) );
3236 while ( !paramElem.isNull() )
3238 const QString name = paramElem.attribute( QStringLiteral(
"name" ) );
3239 const QString value = paramElem.firstChild().nodeValue();
3241 if ( !name.isEmpty() && !value.isEmpty() )
3242 params[ name ] = value;
3244 paramElem = paramElem.nextSiblingElement( QStringLiteral(
"VendorOption" ) );
3254 if ( newSymbols.userType() == QMetaType::Type::QVariantMap )
3256 return newSymbols.toMap();
3263 QDomElement e = element.firstChildElement();
3264 while ( !e.isNull() )
3266 if ( e.tagName() == QLatin1String(
"prop" ) )
3268 const QString propKey = e.attribute( QStringLiteral(
"k" ) );
3269 const QString propValue = e.attribute( QStringLiteral(
"v" ) );
3270 props[propKey] = propValue;
3272 e = e.nextSiblingElement();
3289 QDomElement e = element.firstChildElement();
3291 while ( !e.isNull() )
3293 if ( e.tagName() == QLatin1String(
"symbol" ) )
3297 symbols.insert( e.attribute( QStringLiteral(
"name" ) ), symbol );
3303 e = e.nextSiblingElement();
3310 QStringList subsymbols;
3312 for ( QMap<QString, QgsSymbol *>::iterator it = symbols.begin(); it != symbols.end(); ++it )
3314 if ( it.key()[0] !=
'@' )
3318 subsymbols.append( it.key() );
3320 QStringList parts = it.key().split(
'@' );
3321 if ( parts.count() < 3 )
3323 QgsDebugError(
"found subsymbol with invalid name: " + it.key() );
3327 const QString symname = parts[1];
3328 const int symlayer = parts[2].toInt();
3330 if ( !symbols.contains( symname ) )
3332 QgsDebugError(
"subsymbol references invalid symbol: " + symname );
3340 QgsDebugError(
"subsymbol references invalid symbol layer: " + QString::number( symlayer ) );
3349 QgsDebugError(
"symbol layer refused subsymbol: " + it.key() );
3356 for (
int i = 0; i < subsymbols.count(); i++ )
3357 symbols.take( subsymbols[i] );
3364 QDomElement symbolsElem = doc.createElement( tagName );
3367 for ( QMap<QString, QgsSymbol *>::iterator its = symbols.begin(); its != symbols.end(); ++its )
3369 const QDomElement symEl =
saveSymbol( its.key(), its.value(), doc, context );
3370 symbolsElem.appendChild( symEl );
3378 qDeleteAll( symbols );
3387 std::unique_ptr< QMimeData >mimeData(
new QMimeData );
3389 QDomDocument symbolDoc;
3391 symbolDoc.appendChild( symbolElem );
3392 mimeData->setText( symbolDoc.toString() );
3395 mimeData->setColorData( symbol->
color() );
3397 return mimeData.release();
3405 const QString text = data->text();
3406 if ( !text.isEmpty() )
3411 if ( doc.setContent( text ) )
3413 elem = doc.documentElement();
3415 if ( elem.nodeName() != QLatin1String(
"symbol" ) )
3416 elem = elem.firstChildElement( QStringLiteral(
"symbol" ) );
3427 const QString rampType = element.attribute( QStringLiteral(
"type" ) );
3452 QDomElement rampEl = doc.createElement( QStringLiteral(
"colorramp" ) );
3453 rampEl.setAttribute( QStringLiteral(
"type" ), ramp->
type() );
3454 rampEl.setAttribute( QStringLiteral(
"name" ), name );
3462 QVariantMap rampMap;
3464 rampMap.insert( QStringLiteral(
"type" ), ramp->
type() );
3465 rampMap.insert( QStringLiteral(
"name" ), name );
3467 const QVariantMap properties = ramp->
properties();
3469 QVariantMap propertyMap;
3470 for (
auto property = properties.constBegin();
property != properties.constEnd(); ++property )
3472 propertyMap.insert( property.key(),
property.value() );
3475 rampMap.insert( QStringLiteral(
"properties" ), propertyMap );
3481 const QVariantMap rampMap = value.toMap();
3483 const QString rampType = rampMap.
value( QStringLiteral(
"type" ) ).toString();
3486 const QVariantMap propertyMap = rampMap.value( QStringLiteral(
"properties" ) ).toMap();
3489 for (
auto property = propertyMap.constBegin();
property != propertyMap.constEnd(); ++property )
3491 props.insert( property.key(),
property.value().toString() );
3513 if ( !color.isValid() )
3520 return color.name();
3525 QList<QColor> colors;
3528 const thread_local QRegularExpression sepCommaSpaceRegExp(
"(,|\\s)" );
3529 QStringList components = colorStr.simplified().split( sepCommaSpaceRegExp );
3530 QStringList::iterator it = components.begin();
3531 for ( ; it != components.end(); ++it )
3533 const QColor result =
parseColor( *it,
true );
3534 if ( result.isValid() )
3539 if ( colors.length() > 0 )
3545 const thread_local QRegularExpression sepCommaRegExp(
"(,|\n)" );
3546 components = colorStr.split( sepCommaRegExp );
3547 it = components.begin();
3548 for ( ; it != components.end(); ++it )
3550 const QColor result =
parseColor( *it,
true );
3551 if ( result.isValid() )
3556 if ( colors.length() > 0 )
3562 components = colorStr.simplified().split( QString(
' ' ) );
3563 it = components.begin();
3564 for ( ; it != components.end(); ++it )
3566 const QColor result =
parseColor( *it,
true );
3567 if ( result.isValid() )
3572 if ( colors.length() > 0 )
3578 components = colorStr.split(
'\n' );
3579 it = components.begin();
3580 for ( ; it != components.end(); ++it )
3582 const QColor result =
parseColor( *it,
true );
3583 if ( result.isValid() )
3596 QMimeData *mimeData =
new QMimeData;
3597 mimeData->setColorData( QVariant( color ) );
3598 mimeData->setText( color.name() );
3605 if ( mimeData->hasColor() )
3607 QColor mimeColor = mimeData->colorData().value<QColor>();
3608 if ( mimeColor.isValid() )
3616 if ( mimeData->hasText() )
3620 if ( textColor.isValid() )
3635 if ( data->hasFormat( QStringLiteral(
"text/xml" ) ) )
3638 const QByteArray encodedData = data->data( QStringLiteral(
"text/xml" ) );
3639 QDomDocument xmlDoc;
3640 xmlDoc.setContent( encodedData );
3642 const QDomElement dragDataElem = xmlDoc.documentElement();
3643 if ( dragDataElem.tagName() == QLatin1String(
"ColorSchemeModelDragData" ) )
3645 const QDomNodeList nodeList = dragDataElem.childNodes();
3646 const int nChildNodes = nodeList.size();
3647 QDomElement currentElem;
3649 for (
int i = 0; i < nChildNodes; ++i )
3651 currentElem = nodeList.at( i ).toElement();
3652 if ( currentElem.isNull() )
3657 QPair< QColor, QString> namedColor;
3659 namedColor.second = currentElem.attribute( QStringLiteral(
"label" ), QString() );
3661 mimeColors << namedColor;
3666 if ( mimeColors.length() == 0 && data->hasFormat( QStringLiteral(
"application/x-colorobject-list" ) ) )
3669 const QByteArray encodedData = data->data( QStringLiteral(
"application/x-colorobject-list" ) );
3670 QDomDocument xmlDoc;
3671 xmlDoc.setContent( encodedData );
3673 const QDomNodeList colorsNodes = xmlDoc.elementsByTagName( QStringLiteral(
"colors" ) );
3674 if ( colorsNodes.length() > 0 )
3676 const QDomElement colorsElem = colorsNodes.at( 0 ).toElement();
3677 const QDomNodeList colorNodeList = colorsElem.childNodes();
3678 const int nChildNodes = colorNodeList.size();
3679 QDomElement currentElem;
3681 for (
int i = 0; i < nChildNodes; ++i )
3684 currentElem = colorNodeList.at( i ).toElement();
3685 if ( currentElem.isNull() )
3690 const QDomNodeList colorNodes = currentElem.elementsByTagName( QStringLiteral(
"color" ) );
3691 const QDomNodeList nameNodes = currentElem.elementsByTagName( QStringLiteral(
"name" ) );
3693 if ( colorNodes.length() > 0 )
3695 const QDomElement colorElem = colorNodes.at( 0 ).toElement();
3697 const QStringList colorParts = colorElem.text().simplified().split(
' ' );
3698 if ( colorParts.length() < 3 )
3703 const int red = colorParts.at( 0 ).toDouble() * 255;
3704 const int green = colorParts.at( 1 ).toDouble() * 255;
3705 const int blue = colorParts.at( 2 ).toDouble() * 255;
3706 QPair< QColor, QString> namedColor;
3707 namedColor.first = QColor( red, green, blue );
3708 if ( nameNodes.length() > 0 )
3710 const QDomElement nameElem = nameNodes.at( 0 ).toElement();
3711 namedColor.second = nameElem.text();
3713 mimeColors << namedColor;
3719 if ( mimeColors.length() == 0 && data->hasText() )
3723 QList< QColor >::iterator it = parsedColors.begin();
3724 for ( ; it != parsedColors.end(); ++it )
3726 mimeColors << qMakePair( *it, QString() );
3730 if ( mimeColors.length() == 0 && data->hasColor() )
3733 const QColor mimeColor = data->colorData().value<QColor>();
3734 if ( mimeColor.isValid() )
3736 mimeColors << qMakePair( mimeColor, QString() );
3746 QMimeData *mimeData =
new QMimeData();
3747 QDomDocument xmlDoc;
3748 QDomElement xmlRootElement = xmlDoc.createElement( QStringLiteral(
"ColorSchemeModelDragData" ) );
3749 xmlDoc.appendChild( xmlRootElement );
3751 QgsNamedColorList::const_iterator colorIt = colorList.constBegin();
3752 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3754 QDomElement namedColor = xmlDoc.createElement( QStringLiteral(
"NamedColor" ) );
3756 namedColor.setAttribute( QStringLiteral(
"label" ), ( *colorIt ).second );
3757 xmlRootElement.appendChild( namedColor );
3759 mimeData->setData( QStringLiteral(
"text/xml" ), xmlDoc.toByteArray() );
3767 colorIt = colorList.constBegin();
3768 QStringList colorListString;
3769 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3771 colorListString << ( *colorIt ).first.name();
3773 mimeData->setText( colorListString.join( QLatin1Char(
'\n' ) ) );
3776 if ( colorList.length() > 0 )
3778 mimeData->setColorData( QVariant( colorList.at( 0 ).first ) );
3786 if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3791 QTextStream stream( &file );
3792 stream <<
"GIMP Palette" << Qt::endl;
3793 if ( paletteName.isEmpty() )
3795 stream <<
"Name: QGIS Palette" << Qt::endl;
3799 stream <<
"Name: " << paletteName << Qt::endl;
3801 stream <<
"Columns: 4" << Qt::endl;
3802 stream <<
'#' << Qt::endl;
3804 for ( QgsNamedColorList::ConstIterator colorIt = colors.constBegin(); colorIt != colors.constEnd(); ++colorIt )
3806 const QColor color = ( *colorIt ).first;
3807 if ( !color.isValid() )
3811 stream << QStringLiteral(
"%1 %2 %3" ).arg( color.red(), 3 ).arg( color.green(), 3 ).arg( color.blue(), 3 );
3812 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << Qt::endl;
3823 if ( !file.open( QIODevice::ReadOnly ) )
3826 return importedColors;
3829 QTextStream in( &file );
3831 QString line = in.readLine();
3832 if ( !line.startsWith( QLatin1String(
"GIMP Palette" ) ) )
3835 return importedColors;
3839 while ( !in.atEnd() && !line.startsWith( QLatin1String(
"Name:" ) ) && !line.startsWith(
'#' ) )
3841 line = in.readLine();
3843 if ( line.startsWith( QLatin1String(
"Name:" ) ) )
3845 const thread_local QRegularExpression nameRx(
"Name:\\s*(\\S.*)$" );
3846 const QRegularExpressionMatch match = nameRx.match( line );
3847 if ( match.hasMatch() )
3849 name = match.captured( 1 );
3854 while ( !in.atEnd() && !line.startsWith(
'#' ) )
3856 line = in.readLine();
3861 return importedColors;
3865 const thread_local QRegularExpression rx(
"^\\s*(\\d+)\\s+(\\d+)\\s+(\\d+)(\\s.*)?$" );
3866 while ( !in.atEnd() )
3868 line = in.readLine();
3869 const QRegularExpressionMatch match = rx.match( line );
3870 if ( !match.hasMatch() )
3874 const int red = match.captured( 1 ).toInt();
3875 const int green = match.captured( 2 ).toInt();
3876 const int blue = match.captured( 3 ).toInt();
3877 const QColor color = QColor( red, green, blue );
3878 if ( !color.isValid() )
3885 if ( rx.captureCount() > 3 )
3887 label = match.captured( 4 ).simplified();
3894 importedColors << qMakePair( color, label );
3899 return importedColors;
3912 const thread_local QRegularExpression hexColorAlphaRx(
"^\\s*#?([0-9a-fA-F]{6})([0-9a-fA-F]{2})\\s*$" );
3913 QRegularExpressionMatch match = hexColorAlphaRx.match( colorStr );
3916 if ( !match.hasMatch() && QColor::isValidColor( colorStr ) )
3919 parsedColor.setNamedColor( colorStr );
3920 if ( parsedColor.isValid() )
3922 containsAlpha =
false;
3928 if ( match.hasMatch() )
3930 const QString hexColor = match.captured( 1 );
3931 parsedColor.setNamedColor( QStringLiteral(
"#" ) + hexColor );
3933 const int alphaHex = match.captured( 2 ).toInt( &alphaOk, 16 );
3935 if ( parsedColor.isValid() && alphaOk )
3937 parsedColor.setAlpha( alphaHex );
3938 containsAlpha =
true;
3946 const thread_local QRegularExpression hexColorRx2(
"^\\s*(?:[0-9a-fA-F]{3}){1,2}\\s*$" );
3947 if ( colorStr.indexOf( hexColorRx2 ) != -1 )
3950 parsedColor.setNamedColor( QStringLiteral(
"#" ) + colorStr );
3951 if ( parsedColor.isValid() )
3953 containsAlpha =
false;
3960 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*$" );
3961 match = rgbFormatRx.match( colorStr );
3962 if ( match.hasMatch() )
3967 const int r = match.captured( 1 ).toInt( &rOk );
3968 const int g = match.captured( 2 ).toInt( &gOk );
3969 const int b = match.captured( 3 ).toInt( &bOk );
3971 if ( !rOk || !gOk || !bOk )
3973 const float rFloat = match.captured( 1 ).toFloat();
3974 const float gFloat = match.captured( 2 ).toFloat();
3975 const float bFloat = match.captured( 3 ).toFloat();
3976 parsedColor.setRgbF( rFloat / 255.0, gFloat / 255.0, bFloat / 255.0 );
3980 parsedColor.setRgb( r, g, b );
3983 if ( parsedColor.isValid() )
3985 containsAlpha =
false;
3991 const thread_local QRegularExpression hslFormatRx(
"^\\s*hsl\\(?\\s*(\\d+(?:\\.\\d*)?)\\s*,\\s*(\\d+(?:\\.\\d*)?)\\s*%\\s*,\\s*(\\d+(?:\\.\\d*)?)\\s*%\\s*\\)?\\s*;?\\s*$" );
3992 match = hslFormatRx.match( colorStr );
3993 if ( match.hasMatch() )
3998 const int h = match.captured( 1 ).toInt( &hOk );
3999 const int s = match.captured( 2 ).toInt( &sOk );
4000 const int l = match.captured( 3 ).toInt( &lOk );
4002 if ( !hOk || !sOk || !lOk )
4004 const float hFloat = match.captured( 1 ).toFloat();
4005 const float sFloat = match.captured( 2 ).toFloat();
4006 const float lFloat = match.captured( 3 ).toFloat();
4007 parsedColor.setHslF( hFloat / 360.0, sFloat / 100.0, lFloat / 100.0 );
4011 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0 );
4013 if ( parsedColor.isValid() )
4015 containsAlpha =
false;
4021 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*$" );
4022 match = rgbPercentFormatRx.match( colorStr );
4023 if ( match.hasMatch() )
4025 const double r = match.captured( 1 ).toDouble() / 100;
4026 const double g = match.captured( 2 ).toDouble() / 100;
4027 const double b = match.captured( 3 ).toDouble() / 100;
4028 parsedColor.setRgbF( r, g, b );
4029 if ( parsedColor.isValid() )
4031 containsAlpha =
false;
4037 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*$" );
4038 match = rgbaFormatRx.match( colorStr );
4039 if ( match.hasMatch() )
4044 const int r = match.captured( 1 ).toInt( &rOk );
4045 const int g = match.captured( 2 ).toInt( &gOk );
4046 const int b = match.captured( 3 ).toInt( &bOk );
4047 const double aDouble = match.captured( 4 ).toDouble();
4049 if ( !rOk || !gOk || !bOk )
4051 const float rFloat = match.captured( 1 ).toFloat();
4052 const float gFloat = match.captured( 2 ).toFloat();
4053 const float bFloat = match.captured( 3 ).toFloat();
4054 parsedColor.setRgbF( rFloat / 255.0, gFloat / 255.0, bFloat / 255.0, aDouble );
4058 const int a =
static_cast< int >( std::round( match.captured( 4 ).toDouble() * 255.0 ) );
4059 parsedColor.setRgb( r, g, b, a );
4061 if ( parsedColor.isValid() )
4063 containsAlpha =
true;
4069 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*$" );
4070 match = rgbaPercentFormatRx.match( colorStr );
4071 if ( match.hasMatch() )
4073 const double r = match.captured( 1 ).toDouble() / 100;
4074 const double g = match.captured( 2 ).toDouble() / 100;
4075 const double b = match.captured( 3 ).toDouble() / 100;
4076 const double a = match.captured( 4 ).toDouble();
4077 parsedColor.setRgbF( r, g, b, a );
4078 if ( parsedColor.isValid() )
4080 containsAlpha =
true;
4086 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*$" );
4087 match = hslaPercentFormatRx.match( colorStr );
4088 if ( match.hasMatch() )
4093 const int h = match.captured( 1 ).toInt( &hOk );
4094 const int s = match.captured( 2 ).toInt( &sOk );
4095 const int l = match.captured( 3 ).toInt( &lOk );
4096 const double aDouble = match.captured( 4 ).toDouble();
4098 if ( !hOk || !sOk || !lOk )
4100 const float hFloat = match.captured( 1 ).toFloat();
4101 const float sFloat = match.captured( 2 ).toFloat();
4102 const float lFloat = match.captured( 3 ).toFloat();
4103 parsedColor.setHslF( hFloat / 360.0, sFloat / 100.0, lFloat / 100.0, aDouble );
4107 const int a = std::round( aDouble * 255.0 );
4108 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0, a );
4111 if ( parsedColor.isValid() )
4113 containsAlpha =
true;
4130 const QImage::Format format = image->format();
4131 if ( format != QImage::Format_ARGB32_Premultiplied && format != QImage::Format_ARGB32 )
4138 for (
int heightIndex = 0; heightIndex < image->height(); ++heightIndex )
4140 QRgb *scanLine =
reinterpret_cast< QRgb *
>( image->scanLine( heightIndex ) );
4141 for (
int widthIndex = 0; widthIndex < image->width(); ++widthIndex )
4143 myRgb = scanLine[widthIndex];
4144 if ( format == QImage::Format_ARGB32_Premultiplied )
4145 scanLine[widthIndex] = qRgba( opacity * qRed( myRgb ), opacity * qGreen( myRgb ), opacity * qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4147 scanLine[widthIndex] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4155 const int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
4156 const int alpha = ( radius < 1 ) ? 16 : ( radius > 17 ) ? 1 : tab[radius - 1];
4158 if ( image.format() != QImage::Format_ARGB32_Premultiplied
4159 && image.format() != QImage::Format_RGB32 )
4161 image = image.convertToFormat( QImage::Format_ARGB32_Premultiplied );
4164 const int r1 = rect.top();
4165 const int r2 = rect.bottom();
4166 const int c1 = rect.left();
4167 const int c2 = rect.right();
4169 const int bpl = image.bytesPerLine();
4177 i1 = i2 = ( QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3 );
4179 for (
int col = c1; col <= c2; col++ )
4181 p = image.scanLine( r1 ) + col * 4;
4182 for (
int i = i1; i <= i2; i++ )
4183 rgba[i] = p[i] << 4;
4186 for (
int j = r1; j < r2; j++, p += bpl )
4187 for (
int i = i1; i <= i2; i++ )
4188 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4191 for (
int row = r1; row <= r2; row++ )
4193 p = image.scanLine( row ) + c1 * 4;
4194 for (
int i = i1; i <= i2; i++ )
4195 rgba[i] = p[i] << 4;
4198 for (
int j = c1; j < c2; j++, p += 4 )
4199 for (
int i = i1; i <= i2; i++ )
4200 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4203 for (
int col = c1; col <= c2; col++ )
4205 p = image.scanLine( r2 ) + col * 4;
4206 for (
int i = i1; i <= i2; i++ )
4207 rgba[i] = p[i] << 4;
4210 for (
int j = r1; j < r2; j++, p -= bpl )
4211 for (
int i = i1; i <= i2; i++ )
4212 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4215 for (
int row = r1; row <= r2; row++ )
4217 p = image.scanLine( row ) + c2 * 4;
4218 for (
int i = i1; i <= i2; i++ )
4219 rgba[i] = p[i] << 4;
4222 for (
int j = c1; j < c2; j++, p -= 4 )
4223 for (
int i = i1; i <= i2; i++ )
4224 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4230 if ( alpha != 255 && alpha > 0 )
4234 const double alphaFactor = alpha / 255.;
4235 int r = 0, g = 0, b = 0;
4236 rgb.getRgb( &r, &g, &b );
4241 rgb.setRgb( r, g, b, alpha );
4243 else if ( alpha == 0 )
4245 rgb.setRgb( 0, 0, 0, 0 );
4254 if ( !simpleFill || !simpleLine )
4278 if ( simpleLine->
offset() )
4296 if ( order == Qt::AscendingOrder )
4310 const double dx = directionPoint.x() - startPoint.x();
4311 const double dy = directionPoint.y() - startPoint.y();
4312 const double length = std::sqrt( dx * dx + dy * dy );
4313 const double scaleFactor = distance / length;
4314 return QPointF( startPoint.x() + dx * scaleFactor, startPoint.y() + dy * scaleFactor );
4324 for (
int i = 0; i < svgPaths.size(); i++ )
4326 const QDir dir( svgPaths[i] );
4327 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4328 for (
const QString &item : svgSubPaths )
4330 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4333 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4334 for (
const QString &item : svgFiles )
4337 list.append( dir.path() +
'/' + item );
4349 QStringList svgPaths;
4350 svgPaths.append( directory );
4352 for (
int i = 0; i < svgPaths.size(); i++ )
4354 const QDir dir( svgPaths[i] );
4355 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4356 for (
const QString &item : svgSubPaths )
4358 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4361 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4362 for (
const QString &item : svgFiles )
4364 list.append( dir.path() +
'/' + item );
4376 if ( n.startsWith( QLatin1String(
"base64:" ) ) )
4380 if ( QFileInfo::exists( n ) )
4381 return QFileInfo( n ).canonicalFilePath();
4385 if ( name.contains( QLatin1String(
"://" ) ) )
4387 const QUrl url( name );
4388 if ( url.isValid() && !url.scheme().isEmpty() )
4390 if ( url.scheme().compare( QLatin1String(
"file" ), Qt::CaseInsensitive ) == 0 )
4393 name = url.toLocalFile();
4394 if ( QFile( name ).exists() )
4396 return QFileInfo( name ).canonicalFilePath();
4410 for (
int i = 0; i < svgPaths.size(); i++ )
4412 QString svgPath = svgPaths[i];
4413 if ( svgPath.endsWith( QChar(
'/' ) ) )
4424 const QString myLocalPath = svgPath + QDir::separator() + name;
4427 if ( QFile( myLocalPath ).exists() )
4430 return QFileInfo( myLocalPath ).canonicalFilePath();
4434 return pathResolver.
readPath( name );
4442 if ( p.startsWith( QLatin1String(
"base64:" ) ) )
4445 if ( !QFileInfo::exists( p ) )
4448 QString path = QFileInfo( p ).canonicalFilePath();
4452 bool isInSvgPaths =
false;
4453 for (
int i = 0; i < svgPaths.size(); i++ )
4455 const QString dir = QFileInfo( svgPaths[i] ).canonicalFilePath();
4457 if ( !dir.isEmpty() && path.startsWith( dir ) )
4459 path = path.mid( dir.size() + 1 );
4460 isInSvgPaths =
true;
4473 const double *srcX = line->
xData();
4474 const double *srcY = line->
yData();
4476 QPolygonF thisRes( count );
4477 QPointF *dest = thisRes.data();
4478 for (
int i = 0; i < count; ++i )
4480 *dest++ = QPointF( *srcX++, *srcY++ );
4487 if (
const QgsLineString *line = qgsgeometry_cast< const QgsLineString * >( curve ) )
4493 const std::unique_ptr< QgsLineString > straightened( curve->
curveToLine() );
4509 points << QPointF( ( *it ).x(), ( *it ).y() );
4513 points << QPointF( 0, 0 );
4515 return QList< QList<QPolygonF> >() << ( QList< QPolygonF >() << points );
4520 QList< QList<QPolygonF> > res;
4525 res << ( QList< QPolygonF >() <<
curveToPolygonF( qgsgeometry_cast< const QgsCurve * >( *it ) ) );
4533 QList< QList<QPolygonF> > res;
4537 QList<QPolygonF> thisPart;
4538 const QgsCurvePolygon *surface = qgsgeometry_cast< const QgsCurvePolygon * >( *it );
4556 return QList< QList<QPolygonF> >();
4559 return QList< QList<QPolygonF> >();
4566 double cx = 0, cy = 0;
4567 double area, sum = 0;
4568 for (
int i = points.count() - 1, j = 0; j < points.count(); i = j++ )
4570 const QPointF &p1 = points[i];
4571 const QPointF &p2 = points[j];
4572 area = p1.x() * p2.y() - p1.y() * p2.x();
4574 cx += ( p1.x() + p2.x() ) * area;
4575 cy += ( p1.y() + p2.y() ) * area;
4582 if ( points.count() >= 2 )
4583 return QPointF( ( points[0].x() + points[1].x() ) / 2, ( points[0].y() + points[1].y() ) / 2 );
4584 else if ( points.count() == 1 )
4592 return QPointF( cx, cy );
4599 if ( ( rings && rings->count() > 0 ) || !
pointInPolygon( points, centroid ) )
4601 unsigned int i, pointCount = points.count();
4603 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( points[i].x(), points[i].y() );
4609 for (
auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
4611 pointCount = ( *ringIt ).count();
4613 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( ( *ringIt )[i].x(), ( *ringIt )[i].y() );
4619 if ( !pointOnSurfaceGeom.
isNull() )
4622 centroid.
setX( point.
x() );
4623 centroid.
setY( point.
y() );
4628 return QPointF( centroid.
x(), centroid.
y() );
4633 bool inside =
false;
4635 const double x = point.x();
4636 const double y = point.y();
4638 for (
int i = 0, j = points.count() - 1; i < points.count(); i++ )
4640 const QPointF &p1 = points[i];
4641 const QPointF &p2 = points[j];
4646 if ( ( p1.y() < y && p2.y() >= y ) || ( p2.y() < y && p1.y() >= y ) )
4648 if ( p1.x() + ( y - p1.y() ) / ( p2.y() - p1.y() ) * ( p2.x() - p1.x() ) <= x )
4659 if ( polyline.size() < 2 )
4662 double totalLength = 0;
4663 auto it = polyline.begin();
4665 for ( ; it != polyline.end(); ++it )
4667 const QPointF p2 = *it;
4668 const double segmentLength = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4669 totalLength += segmentLength;
4677 if ( polyline.size() < 2 )
4680 double totalLength = 0;
4681 auto it = polyline.begin();
4683 std::vector< double > segmentLengths( polyline.size() - 1 );
4684 auto segmentLengthIt = segmentLengths.begin();
4685 for ( ; it != polyline.end(); ++it )
4687 const QPointF p2 = *it;
4688 *segmentLengthIt = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4689 totalLength += *segmentLengthIt;
4695 if ( startOffset >= 0 && totalLength <= startOffset )
4697 if ( endOffset < 0 && totalLength <= -endOffset )
4700 const double startDistance = startOffset < 0 ? totalLength + startOffset : startOffset;
4701 const double endDistance = endOffset <= 0 ? totalLength + endOffset : endOffset;
4702 QPolygonF substringPoints;
4703 substringPoints.reserve( polyline.size() );
4705 it = polyline.begin();
4706 segmentLengthIt = segmentLengths.begin();
4709 bool foundStart =
false;
4710 if (
qgsDoubleNear( startDistance, 0.0 ) || startDistance < 0 )
4712 substringPoints << p1;
4716 double distanceTraversed = 0;
4717 for ( ; it != polyline.end(); ++it )
4719 const QPointF p2 = *it;
4720 if ( distanceTraversed < startDistance && distanceTraversed + *segmentLengthIt > startDistance )
4723 const double distanceToStart = startDistance - distanceTraversed;
4724 double startX, startY;
4726 substringPoints << QPointF( startX, startY );
4729 if ( foundStart && ( distanceTraversed + *segmentLengthIt > endDistance ) )
4732 const double distanceToEnd = endDistance - distanceTraversed;
4735 if ( substringPoints.last() != QPointF( endX, endY ) )
4736 substringPoints << QPointF( endX, endY );
4738 else if ( foundStart )
4740 if ( substringPoints.last() != QPointF( p2.x(), p2.y() ) )
4741 substringPoints << QPointF( p2.x(), p2.y() );
4744 distanceTraversed += *segmentLengthIt;
4745 if ( distanceTraversed > endDistance )
4752 if ( ( substringPoints.size() < 2 ) || ( substringPoints.size() == 2 && substringPoints.at( 0 ) == substringPoints.at( 1 ) ) )
4755 return substringPoints;
4760 double vertexAngle = M_PI - ( std::atan2( p3.y() - p2.y(), p3.x() - p2.x() ) - std::atan2( p2.y() - p1.y(), p2.x() - p1.x() ) );
4764 return vertexAngle < M_PI * 135.0 / 180.0 || vertexAngle > M_PI * 225.0 / 180.0;
4769 target.reserve( target.size() + line.size() );
4770 for (
const QPointF &pt : line )
4772 if ( !target.empty() && target.last() == pt )
4781 if ( fieldOrExpression.isEmpty() )
4816 QList<double> breaks;
4819 breaks.append( maximum );
4823 const int minimumCount =
static_cast< int >( classes ) / 3;
4824 const double shrink = 0.75;
4825 const double highBias = 1.5;
4826 const double adjustBias = 0.5 + 1.5 * highBias;
4827 const int divisions = classes;
4828 const double h = highBias;
4831 const double dx = maximum - minimum;
4841 cell = std::max( std::fabs( minimum ), std::fabs( maximum ) );
4842 if ( adjustBias >= 1.5 * h + 0.5 )
4844 U = 1 + ( 1.0 / ( 1 + h ) );
4848 U = 1 + ( 1.5 / ( 1 + adjustBias ) );
4850 small = dx < ( cell * U * std::max( 1, divisions ) * 1e-07 * 3.0 );
4857 cell = 9 + cell / 10;
4858 cell = cell * shrink;
4860 if ( minimumCount > 1 )
4862 cell = cell / minimumCount;
4868 if ( divisions > 1 )
4870 cell = cell / divisions;
4873 if ( cell < 20 * 1e-07 )
4878 const double base = std::pow( 10.0, std::floor( std::log10( cell ) ) );
4880 if ( ( 2 * base ) - cell < h * ( cell - unit ) )
4883 if ( ( 5 * base ) - cell < adjustBias * ( cell - unit ) )
4886 if ( ( 10.0 * base ) - cell < h * ( cell - unit ) )
4893 int start = std::floor( minimum / unit + 1e-07 );
4894 int end = std::ceil( maximum / unit - 1e-07 );
4897 while ( start * unit > minimum + ( 1e-07 * unit ) )
4901 while ( end * unit < maximum - ( 1e-07 * unit ) )
4909 int k = std::floor( 0.5 + end - start );
4910 if ( k < minimumCount )
4912 k = minimumCount - k;
4916 start = start - k / 2 + k % 2;
4920 start = start - k / 2;
4921 end = end + k / 2 + k % 2;
4924 const double minimumBreak = start * unit;
4926 const int count = end - start;
4928 breaks.reserve( count );
4929 for (
int i = 1; i < count + 1; i++ )
4931 breaks.append( minimumBreak + i * unit );
4934 if ( breaks.isEmpty() )
4937 if ( breaks.first() < minimum )
4939 breaks[0] = minimum;
4941 if ( breaks.last() > maximum )
4943 breaks[breaks.count() - 1] = maximum;
4948 if ( minimum < 0.0 && maximum > 0.0 )
4950 QList<double> breaksMinusZero;
4951 for (
int i = 0; i < breaks.count(); i++ )
4953 breaksMinusZero.append( breaks[i] - 0.0 );
4956 for (
int i = 1; i < breaks.count(); i++ )
4958 if ( std::abs( breaksMinusZero[i] ) < std::abs( breaksMinusZero[i - 1] ) )
4961 breaks[posOfMin] = 0.0;
4970 bool roundToUnit =
false;
4973 if ( props.contains( QStringLiteral(
"uomScale" ) ) )
4976 scale = props.value( QStringLiteral(
"uomScale" ) ).toDouble( &ok );
4985 if ( props.value( QStringLiteral(
"uom" ) ) == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
5010 scale = 1 / 0.28 * 25.4;
5034 double rescaled = size * scale;
5039 rescaled = std::round( rescaled );
5046 const double x =
rescaleUom( point.x(), unit, props );
5047 const double y =
rescaleUom( point.y(), unit, props );
5048 return QPointF( x, y );
5053 QVector<qreal> result;
5054 QVector<qreal>::const_iterator it = array.constBegin();
5055 for ( ; it != array.constEnd(); ++it )
5057 result.append(
rescaleUom( *it, unit, props ) );
5064 if ( !props.value( QStringLiteral(
"scaleMinDenom" ), QString() ).toString().isEmpty() )
5066 QDomElement scaleMinDenomElem = doc.createElement( QStringLiteral(
"se:MinScaleDenominator" ) );
5067 scaleMinDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMinDenom" ) ).toString().toDouble() ) ) );
5068 ruleElem.appendChild( scaleMinDenomElem );
5071 if ( !props.value( QStringLiteral(
"scaleMaxDenom" ), QString() ).toString().isEmpty() )
5073 QDomElement scaleMaxDenomElem = doc.createElement( QStringLiteral(
"se:MaxScaleDenominator" ) );
5074 scaleMaxDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMaxDenom" ) ).toString().toDouble() ) ) );
5075 ruleElem.appendChild( scaleMaxDenomElem );
5084 const double parentScaleMinDenom = props.value( QStringLiteral(
"scaleMinDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
5085 if ( !ok || parentScaleMinDenom <= 0 )
5086 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( mScaleMinDenom );
5088 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( std::max( parentScaleMinDenom, mScaleMinDenom ) );
5094 const double parentScaleMaxDenom = props.value( QStringLiteral(
"scaleMaxDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
5095 if ( !ok || parentScaleMaxDenom <= 0 )
5096 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( mScaleMaxDenom );
5098 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( std::min( parentScaleMaxDenom, mScaleMaxDenom ) );
5106 if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
5108 scale = 1.0 / 0.00028;
5110 else if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
5112 scale = 304.8 / 0.28;
5119 return size * scale;
5128 SymbolLayerVisitor(
const QSet<QgsSymbolLayerId> &layerIds )
5129 : mSymbolLayerIds( layerIds )
5142 void visitSymbol(
const QgsSymbol *symbol,
const QString &identifier, QVector<int> rootPath )
5146 QVector<int> indexPath = rootPath;
5147 indexPath.append( idx );
5150 if ( mSymbolLayerIds.contains(
QgsSymbolLayerId( mCurrentRuleKey + identifier, indexPath ) ) )
5152 mSymbolLayers.insert( sl );
5158 visitSymbol( subSymbol, identifier, indexPath );
5167 if ( symbolEntity->symbol() )
5169 visitSymbol( symbolEntity->symbol(), leaf.
identifier, {} );
5175 QString mCurrentRuleKey;
5176 const QSet<QgsSymbolLayerId> &mSymbolLayerIds;
5177 QSet<const QgsSymbolLayer *> mSymbolLayers;
5181 SymbolLayerVisitor visitor( symbolLayerIds );
5182 renderer->
accept( &visitor );
5183 return visitor.mSymbolLayers;
5191 SymbolRefreshRateVisitor()
5203 void visitSymbol(
const QgsSymbol *symbol )
5220 if ( refreshRate == -1 || ( animatedMarker->frameRate() > refreshRate ) )
5221 refreshRate = animatedMarker->frameRate();
5225 visitSymbol( subSymbol );
5233 if (
QgsSymbol *symbol = qgis::down_cast<const QgsStyleSymbolEntity *>( leaf.
entity )->symbol() )
5235 visitSymbol( symbol );
5241 double refreshRate = -1;
5244 SymbolRefreshRateVisitor visitor;
5245 renderer->
accept( &visitor );
5246 return visitor.refreshRate;
5251 if ( !s || !context )
5277 size = markerSymbol->
size( *context );
5279 else if ( lineSymbol )
5281 size = lineSymbol->
width( *context );
5293 if ( minSize > 0 && size < minSize )
5297 else if ( maxSize > 0 && size > maxSize )
5316 else if ( lineSymbol )
5331 QMap<QString, QgsProperty>::const_iterator paramIt = propertiesMap.constBegin();
5332 for ( ; paramIt != propertiesMap.constEnd(); ++paramIt )
5334 properties.insert( paramIt.key(), paramIt.value().valueAsString( context ) );
5342 angleRad = std::fmod( angleRad, M_PI * 2 );
5346 angleRad += M_PI * 2;
5350 struct rationalTangent
5362 static const QList<rationalTangent> __rationalTangents
5364 { 1, 57, 0.01754206006 },
5365 { 3, 86, 0.03486958155 },
5366 { 1, 19, 0.05258306161 },
5367 { 3, 43, 0.06965457373 },
5368 { 7, 80, 0.08727771295 },
5369 { 2, 19, 0.1048769387 },
5370 { 7, 57, 0.1221951707 },
5371 { 9, 64, 0.1397088743 },
5372 { 13, 82, 0.157228051 },
5373 { 3, 17, 0.174672199 },
5374 { 7, 36, 0.1920480172 },
5375 { 17, 80, 0.209385393 },
5376 { 3, 13, 0.2267988481 },
5377 { 1, 4, 0.2449786631 },
5378 { 26, 97, 0.2618852647 },
5379 { 27, 94, 0.2797041525 },
5380 { 26, 85, 0.2968446734 },
5381 { 13, 40, 0.3142318991 },
5382 { 21, 61, 0.3315541619 },
5383 { 4, 11, 0.3487710036 },
5384 { 38, 99, 0.3664967859 },
5385 { 40, 99, 0.383984624 },
5386 { 31, 73, 0.4015805401 },
5387 { 41, 92, 0.4192323938 },
5388 { 7, 15, 0.4366271598 },
5389 { 20, 41, 0.4538440015 },
5390 { 27, 53, 0.4711662643 },
5391 { 42, 79, 0.4886424026 },
5392 { 51, 92, 0.5061751436 },
5393 { 56, 97, 0.5235757641 },
5394 { 3, 5, 0.5404195003 },
5395 { 5, 8, 0.5585993153 },
5396 { 50, 77, 0.5759185996 },
5397 { 29, 43, 0.5933501462 },
5398 { 7, 10, 0.6107259644 },
5399 { 69, 95, 0.6281701124 },
5400 { 52, 69, 0.6458159195 },
5401 { 25, 32, 0.6632029927 },
5402 { 17, 21, 0.6805212247 },
5403 { 73, 87, 0.6981204504 },
5404 { 73, 84, 0.7154487784 },
5405 { 9, 10, 0.7328151018 },
5406 { 83, 89, 0.7505285818 },
5407 { 28, 29, 0.7678561033 },
5408 { 1, 1, 0.7853981634 },
5409 { 29, 28, 0.8029402235 },
5410 { 89, 83, 0.820267745 },
5411 { 10, 9, 0.837981225 },
5412 { 107, 93, 0.855284165 },
5413 { 87, 73, 0.8726758763 },
5414 { 121, 98, 0.8900374031 },
5415 { 32, 25, 0.9075933341 },
5416 { 69, 52, 0.9249804073 },
5417 { 128, 93, 0.9424647244 },
5418 { 10, 7, 0.9600703624 },
5419 { 43, 29, 0.9774461806 },
5420 { 77, 50, 0.9948777272 },
5421 { 8, 5, 1.012197011 },
5422 { 163, 98, 1.029475114 },
5423 { 168, 97, 1.047174539 },
5424 { 175, 97, 1.064668696 },
5425 { 126, 67, 1.082075603 },
5426 { 157, 80, 1.099534652 },
5427 { 203, 99, 1.117049384 },
5428 { 193, 90, 1.134452855 },
5429 { 146, 65, 1.151936673 },
5430 { 139, 59, 1.169382787 },
5431 { 99, 40, 1.186811703 },
5432 { 211, 81, 1.204257817 },
5433 { 272, 99, 1.221730164 },
5434 { 273, 94, 1.239188479 },
5435 { 277, 90, 1.25664606 },
5436 { 157, 48, 1.274088705 },
5437 { 279, 80, 1.291550147 },
5438 { 362, 97, 1.308990773 },
5439 { 373, 93, 1.326448578 },
5440 { 420, 97, 1.343823596 },
5441 { 207, 44, 1.361353157 },
5442 { 427, 83, 1.378810994 },
5443 { 414, 73, 1.396261926 },
5444 { 322, 51, 1.413716057 },
5445 { 185, 26, 1.431170275 },
5446 { 790, 97, 1.448623034 },
5447 { 333, 35, 1.466075711 },
5448 { 1063, 93, 1.483530284 },
5449 { 1330, 93, 1.500985147 },
5450 { 706, 37, 1.518436297 },
5451 { 315, 11, 1.535889876 },
5452 { 3953, 69, 1.553343002 },
5458 static const QList<rationalTangent> rationalTangents
5460 { 1, 10, qDegreesToRadians( 5.71059 ) },
5461 { 1, 5, qDegreesToRadians( 11.3099 ) },
5462 { 1, 4, qDegreesToRadians( 14.0362 ) },
5463 { 1, 4, qDegreesToRadians( 18.4349 ) },
5464 { 1, 2, qDegreesToRadians( 26.5651 ) },
5465 { 2, 3, qDegreesToRadians( 33.6901 ) },
5466 { 1, 1, qDegreesToRadians( 45.0 ) },
5467 { 3, 2, qDegreesToRadians( 56.3099 ) },
5468 { 2, 1, qDegreesToRadians( 63.4349 ) },
5469 { 3, 1, qDegreesToRadians( 71.5651 ) },
5470 { 4, 1, qDegreesToRadians( 75.9638 ) },
5471 { 10, 1, qDegreesToRadians( 84.2894 ) },
5474 const int quadrant {
static_cast<int>( angleRad / M_PI_2 ) };
5475 Q_ASSERT( quadrant >= 0 && quadrant <= 3 );
5487 angleRad -= M_PI / 2;
5497 angleRad -= M_PI + M_PI_2;
5519 for (
int idx = 0; idx < rationalTangents.count(); ++idx )
5521 const auto item = rationalTangents.at( idx );
5522 if (
qgsDoubleNear( item.angle, angleRad, 10E-3 ) || item.angle > angleRad )
5529 const rationalTangent bTan { rationalTangents.at( rTanIdx ) };
5530 angleRad = bTan.angle;
5531 const double k { bTan.q *height *width / std::cos( angleRad ) };
5532 const int hcfH { std::gcd( bTan.p * height, bTan.q * width ) };
5533 const int hcfW { std::gcd( bTan.q * height, bTan.p * width ) };
5534 const int W1 {
static_cast<int>( std::round( k / hcfW ) ) };
5535 const int H1 {
static_cast<int>( std::round( k / hcfH ) ) };
5548 angleRad += M_PI / 2;
5561 angleRad += M_PI + M_PI_2;
5572template <
typename Functor>
5575 sl->
setId( generateId() );
5583template <
typename Functor>
5611 if ( clipGeometries.empty() )
5614 if ( bounds.isNull() )
5615 return clipGeometries;
5619 clipGeometries.erase(
5620 std::remove_if( clipGeometries.begin(), clipGeometries.end(), [&boundsRect](
const QgsGeometry & geometry )
5622 return !geometry.boundingBoxIntersects( boundsRect );
5623 } ), clipGeometries.end() );
5625 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.
@ 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.
@ Flat
Flat cap (in line with start/end of line)
@ 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.
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 double value(int index) const =0
Returns relative value between [0,1] of color at specified index.
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 it 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.
Class for 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.
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
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.
QgsAbstractGeometry::const_part_iterator const_parts_begin() const
Returns STL-style const iterator pointing to the first part of the geometry.
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.
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...
QgsAbstractGeometry::const_part_iterator const_parts_end() const
Returns STL-style iterator pointing to the imaginary part after the last part of the geometry.
QgsAbstractGeometry::vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
QgsAbstractGeometry::vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry.
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).
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.
A class to represent a 2D point.
void setY(double y)
Sets the point's y-coordinate.
void setX(double x)
Sets the point's x-coordinate.
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 a 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.
The class is used as a container of context for various read/write operations on other 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 class for filling symbols 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...
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.
void setIsAnimated(bool animated)
Sets whether the symbol is animated.
void setFrameRate(double rate)
Sets the symbol animation frame rate (in frames per second).
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 is not usable (when a ...
QgsSymbolLayer * createSymbolLayerFromSld(const QString &name, QDomElement &element) const
create a new instance of symbol layer given symbol layer name and SLD
QgsSymbolLayer * createSymbolLayer(const QString &name, const QVariantMap &properties=QVariantMap()) const
create a new instance of symbol layer given symbol layer name and properties
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.
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 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 QgsSymbol * symbolFromMimeData(const QMimeData *data)
Attempts to parse mime data as a symbol.
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 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 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 bool createFunctionElement(QDomDocument &doc, QDomElement &element, const QString &function)
static QColor decodeColor(const QString &str)
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 QgsColorRamp * loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
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 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 QgsNamedColorList colorListFromMimeData(const QMimeData *data)
Attempts to parse mime data as a list of named colors.
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 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 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 void createOpacityElement(QDomDocument &doc, QDomElement &element, const QString &alphaFunc)
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 QDomElement saveColorRamp(const QString &name, QgsColorRamp *ramp, QDomDocument &doc)
Encodes a color ramp's settings to an XML element.
static bool opacityFromSldElement(QDomElement &element, QString &alphaFunc)
static QString encodeSldFontWeight(int weight)
static void externalMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &path, const QString &format, int *markIndex=nullptr, const QColor &color=QColor(), double size=-1)
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 void lineToSld(QDomDocument &doc, QDomElement &element, Qt::PenStyle penStyle, const QColor &color, double width=-1, const Qt::PenJoinStyle *penJoinStyle=nullptr, const Qt::PenCapStyle *penCapStyle=nullptr, const QVector< qreal > *customDashPattern=nullptr, double dashOffset=0.0)
static 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)
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 * loadSymbol(const QDomElement &element, const QgsReadWriteContext &context)
Attempts to load a symbol from a DOM element.
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 QgsSymbolLayer * loadSymbolLayer(QDomElement &element, const QgsReadWriteContext &context)
Reads and returns symbol layer from XML. Caller is responsible for deleting the returned object.
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 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 void fillToSld(QDomDocument &doc, QDomElement &element, Qt::BrushStyle brushStyle, const QColor &color=QColor())
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 Qgis::RenderUnit decodeSldUom(const QString &str, double *scaleFactor=nullptr)
Decodes a SLD unit of measure string to a render unit.
static void createGeometryElement(QDomDocument &doc, QDomElement &element, const QString &geomFunc)
static 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 void wellKnownMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &name, const QColor &color, const QColor &strokeColor, Qt::PenStyle strokeStyle, double strokeWidth=-1, double size=-1)
static QString 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 void createRotationElement(QDomDocument &doc, QDomElement &element, const QString &rotationFunc)
static Qgis::SymbolCoordinateReference decodeCoordinateReference(const QString &string, bool *ok=nullptr)
Decodes a string representing a symbol coordinate reference mode.
static 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 void labelTextToSld(QDomDocument &doc, QDomElement &element, const QString &label, const QFont &font, const QColor &color=QColor(), double size=-1)
static QgsSymbolLayer * createMarkerLayerFromSld(QDomElement &element)
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 QString encodePenJoinStyle(Qt::PenJoinStyle style)
static QgsStringMap getVendorOptionList(QDomElement &element)
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 QgsSymbolLayer * createLineLayerFromSld(QDomElement &element)
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 QgsSymbolLayer * createFillLayerFromSld(QDomElement &element)
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 QgsExpression * fieldOrExpressionToExpression(const QString &fieldOrExpression)
Returns a new valid expression instance for given field or expression string.
static QSizeF decodeSize(const QString &string)
Decodes a QSizeF from a string.
static QString encodeRealVector(const QVector< qreal > &v)
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.
void setPaintEffect(QgsPaintEffect *effect)
Sets the current paint effect for the layer.
void setRenderingPass(int renderingPass)
Specifies the rendering pass in which this symbol layer should be rendered.
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.
void setEnabled(bool enabled)
Sets whether symbol layer is enabled and should be drawn.
virtual QVariantMap properties() const =0
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void setUserFlags(Qgis::SymbolLayerUserFlags flags)
Sets user-controlled flags which control the symbol layer's behavior.
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 void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the layer.
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.
void setLocked(bool locked)
Sets whether the layer's colors are locked.
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.
void setOriginalGeometryType(Qgis::GeometryType type)
Sets the geometry type for the original feature geometry being rendered.
Abstract base class for all rendered symbols.
void setOutputUnit(Qgis::RenderUnit unit) const
Sets the units to use for sizes and widths within the symbol.
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.
void setExtentBuffer(double extentBuffer)
Sets the symbol's extent buffer.
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.
void setMapUnitScale(const QgsMapUnitScale &scale) const
Sets the map unit scale for the symbol.
bool clipFeaturesToExtent() const
Returns whether features drawn by the symbol will be clipped to the render context's extent.
void setFlags(Qgis::SymbolFlags flags)
Sets flags for the symbol.
void setExtentBufferSizeUnit(Qgis::RenderUnit unit)
Sets the unit used for the extent buffer.
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.
void setOpacity(qreal opacity)
Sets the opacity for 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.
void setBufferSettings(QgsSymbolBufferSettings *settings)
Sets a the symbol buffer settings, which control an optional "halo" effect around the symbol.
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-...
void setClipFeaturesToExtent(bool clipFeaturesToExtent)
Sets whether features drawn by the symbol should be clipped to the render context's extent.
void setForceRHR(bool force)
Sets whether polygon features drawn by the symbol should be reoriented to follow the standard right-h...
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.