52#include <QDomDocument>
62#include <QRegularExpression>
65#define POINTS_TO_MM 2.83464567
69 return QStringLiteral(
"%1,%2,%3,%4" ).arg( color.red() ).arg( color.green() ).arg( color.blue() ).arg( color.alpha() );
74 const QStringList lst = str.split(
',' );
75 if ( lst.count() < 3 )
79 int red, green, blue, alpha;
81 green = lst[1].toInt();
82 blue = lst[2].toInt();
84 if ( lst.count() > 3 )
86 alpha = lst[3].toInt();
88 return QColor( red, green, blue, alpha );
93 return QString::number( alpha / 255.0,
'g', 2 );
99 double alpha = str.toDouble( &ok );
100 if ( !ok || alpha > 1 )
102 else if ( alpha < 0 )
111 case QFont::StyleNormal:
112 return QStringLiteral(
"normal" );
113 case QFont::StyleItalic:
114 return QStringLiteral(
"italic" );
115 case QFont::StyleOblique:
116 return QStringLiteral(
"oblique" );
124 if ( str == QLatin1String(
"normal" ) )
return QFont::StyleNormal;
125 if ( str == QLatin1String(
"italic" ) )
return QFont::StyleItalic;
126 if ( str == QLatin1String(
"oblique" ) )
return QFont::StyleOblique;
127 return QFont::StyleNormal;
132 if ( weight == 50 )
return QStringLiteral(
"normal" );
133 if ( weight == 75 )
return QStringLiteral(
"bold" );
137 if ( weight < 0 )
return QStringLiteral(
"100" );
138 if ( weight > 99 )
return QStringLiteral(
"900" );
139 return QString::number( weight * 800 / 99 + 100 );
145 const int weight = str.toInt( &ok );
147 return static_cast< int >( QFont::Normal );
151 if ( weight > 900 )
return 99;
152 if ( weight < 100 )
return 0;
153 return ( weight - 100 ) * 99 / 800;
161 return QStringLiteral(
"no" );
163 return QStringLiteral(
"solid" );
165 return QStringLiteral(
"dash" );
167 return QStringLiteral(
"dot" );
168 case Qt::DashDotLine:
169 return QStringLiteral(
"dash dot" );
170 case Qt::DashDotDotLine:
171 return QStringLiteral(
"dash dot dot" );
173 return QStringLiteral(
"???" );
179 if ( str == QLatin1String(
"no" ) )
return Qt::NoPen;
180 if ( str == QLatin1String(
"solid" ) )
return Qt::SolidLine;
181 if ( str == QLatin1String(
"dash" ) )
return Qt::DashLine;
182 if ( str == QLatin1String(
"dot" ) )
return Qt::DotLine;
183 if ( str == QLatin1String(
"dash dot" ) )
return Qt::DashDotLine;
184 if ( str == QLatin1String(
"dash dot dot" ) )
return Qt::DashDotDotLine;
185 return Qt::SolidLine;
193 return QStringLiteral(
"bevel" );
195 return QStringLiteral(
"miter" );
197 return QStringLiteral(
"round" );
199 return QStringLiteral(
"???" );
205 const QString cleaned = str.toLower().trimmed();
206 if ( cleaned == QLatin1String(
"bevel" ) )
207 return Qt::BevelJoin;
208 if ( cleaned == QLatin1String(
"miter" ) )
209 return Qt::MiterJoin;
210 if ( cleaned == QLatin1String(
"round" ) )
211 return Qt::RoundJoin;
212 return Qt::BevelJoin;
220 return QStringLiteral(
"bevel" );
222 return QStringLiteral(
"mitre" );
224 return QStringLiteral(
"round" );
232 if ( str == QLatin1String(
"bevel" ) )
return Qt::BevelJoin;
233 if ( str == QLatin1String(
"mitre" ) )
return Qt::MiterJoin;
234 if ( str == QLatin1String(
"round" ) )
return Qt::RoundJoin;
235 return Qt::BevelJoin;
243 return QStringLiteral(
"square" );
245 return QStringLiteral(
"flat" );
247 return QStringLiteral(
"round" );
249 return QStringLiteral(
"???" );
255 if ( str == QLatin1String(
"square" ) )
return Qt::SquareCap;
256 if ( str == QLatin1String(
"flat" ) )
return Qt::FlatCap;
257 if ( str == QLatin1String(
"round" ) )
return Qt::RoundCap;
258 return Qt::SquareCap;
266 return QStringLiteral(
"square" );
268 return QStringLiteral(
"butt" );
270 return QStringLiteral(
"round" );
278 if ( str == QLatin1String(
"square" ) )
return Qt::SquareCap;
279 if ( str == QLatin1String(
"butt" ) )
return Qt::FlatCap;
280 if ( str == QLatin1String(
"round" ) )
return Qt::RoundCap;
281 return Qt::SquareCap;
288 case Qt::SolidPattern :
289 return QStringLiteral(
"solid" );
290 case Qt::HorPattern :
291 return QStringLiteral(
"horizontal" );
292 case Qt::VerPattern :
293 return QStringLiteral(
"vertical" );
294 case Qt::CrossPattern :
295 return QStringLiteral(
"cross" );
296 case Qt::BDiagPattern :
297 return QStringLiteral(
"b_diagonal" );
298 case Qt::FDiagPattern :
299 return QStringLiteral(
"f_diagonal" );
300 case Qt::DiagCrossPattern :
301 return QStringLiteral(
"diagonal_x" );
302 case Qt::Dense1Pattern :
303 return QStringLiteral(
"dense1" );
304 case Qt::Dense2Pattern :
305 return QStringLiteral(
"dense2" );
306 case Qt::Dense3Pattern :
307 return QStringLiteral(
"dense3" );
308 case Qt::Dense4Pattern :
309 return QStringLiteral(
"dense4" );
310 case Qt::Dense5Pattern :
311 return QStringLiteral(
"dense5" );
312 case Qt::Dense6Pattern :
313 return QStringLiteral(
"dense6" );
314 case Qt::Dense7Pattern :
315 return QStringLiteral(
"dense7" );
317 return QStringLiteral(
"no" );
319 return QStringLiteral(
"???" );
325 if ( str == QLatin1String(
"solid" ) )
return Qt::SolidPattern;
326 if ( str == QLatin1String(
"horizontal" ) )
return Qt::HorPattern;
327 if ( str == QLatin1String(
"vertical" ) )
return Qt::VerPattern;
328 if ( str == QLatin1String(
"cross" ) )
return Qt::CrossPattern;
329 if ( str == QLatin1String(
"b_diagonal" ) )
return Qt::BDiagPattern;
330 if ( str == QLatin1String(
"f_diagonal" ) )
return Qt::FDiagPattern;
331 if ( str == QLatin1String(
"diagonal_x" ) )
return Qt::DiagCrossPattern;
332 if ( str == QLatin1String(
"dense1" ) )
return Qt::Dense1Pattern;
333 if ( str == QLatin1String(
"dense2" ) )
return Qt::Dense2Pattern;
334 if ( str == QLatin1String(
"dense3" ) )
return Qt::Dense3Pattern;
335 if ( str == QLatin1String(
"dense4" ) )
return Qt::Dense4Pattern;
336 if ( str == QLatin1String(
"dense5" ) )
return Qt::Dense5Pattern;
337 if ( str == QLatin1String(
"dense6" ) )
return Qt::Dense6Pattern;
338 if ( str == QLatin1String(
"dense7" ) )
return Qt::Dense7Pattern;
339 if ( str == QLatin1String(
"no" ) )
return Qt::NoBrush;
340 return Qt::SolidPattern;
347 case Qt::CrossPattern:
348 return QStringLiteral(
"cross" );
349 case Qt::DiagCrossPattern:
350 return QStringLiteral(
"x" );
357 return QStringLiteral(
"horline" );
359 return QStringLiteral(
"line" );
360 case Qt::BDiagPattern:
361 return QStringLiteral(
"slash" );
362 case Qt::FDiagPattern:
363 return QStringLiteral(
"backslash" );
366 case Qt::Dense1Pattern:
367 case Qt::Dense2Pattern:
368 case Qt::Dense3Pattern:
369 case Qt::Dense4Pattern:
370 case Qt::Dense5Pattern:
371 case Qt::Dense6Pattern:
372 case Qt::Dense7Pattern:
382 if ( str == QLatin1String(
"horline" ) )
return Qt::HorPattern;
383 if ( str == QLatin1String(
"line" ) )
return Qt::VerPattern;
384 if ( str == QLatin1String(
"cross" ) )
return Qt::CrossPattern;
385 if ( str == QLatin1String(
"slash" ) )
return Qt::BDiagPattern;
386 if ( str == QLatin1String(
"backshash" ) )
return Qt::FDiagPattern;
387 if ( str == QLatin1String(
"x" ) )
return Qt::DiagCrossPattern;
389 if ( str.startsWith( QLatin1String(
"brush://" ) ) )
405 case Qt::MPenCapStyle:
418 case Qt::SvgMiterJoin:
424 case Qt::MPenJoinStyle:
433 const QDomNodeList children = element.childNodes();
434 for (
int i = 0; i < children.size(); ++i )
436 const QDomElement childElement = children.at( i ).toElement();
437 if ( childElement.tagName() == QLatin1String(
"se:LineSymbolizer" )
438 || childElement.tagName() == QLatin1String(
"se:PointSymbolizer" )
439 || childElement.tagName() == QLatin1String(
"se:PolygonSymbolizer" ) )
447 const QString compareString =
string.trimmed();
451 if ( compareString.compare( QLatin1String(
"feature" ), Qt::CaseInsensitive ) == 0 )
453 else if ( compareString.compare( QLatin1String(
"viewport" ), Qt::CaseInsensitive ) == 0 )
463 switch ( coordinateReference )
466 return QStringLiteral(
"feature" );
468 return QStringLiteral(
"viewport" );
479 const QString s = value.toString().toLower().trimmed();
480 if ( s == QLatin1String(
"single" ) )
482 else if ( s == QLatin1String(
"reversed" ) )
484 else if ( s == QLatin1String(
"double" ) )
486 else if ( value.toInt() == 1 )
488 else if ( value.toInt() == 2 )
490 else if ( value.toInt( &intOk ) == 0 && intOk )
504 const QString s = value.toString().toLower().trimmed();
505 if ( s == QLatin1String(
"plain" ) )
507 else if ( s == QLatin1String(
"lefthalf" ) )
509 else if ( s == QLatin1String(
"righthalf" ) )
511 else if ( value.toInt() == 1 )
513 else if ( value.toInt() == 2 )
515 else if ( value.toInt( &intOk ) == 0 && intOk )
525 const QString compareString =
string.trimmed();
529 if ( compareString.compare( QLatin1String(
"no" ), Qt::CaseInsensitive ) == 0 )
531 else if ( compareString.compare( QLatin1String(
"shape" ), Qt::CaseInsensitive ) == 0 )
533 else if ( compareString.compare( QLatin1String(
"centroid_within" ), Qt::CaseInsensitive ) == 0 )
535 else if ( compareString.compare( QLatin1String(
"completely_within" ), Qt::CaseInsensitive ) == 0 )
548 return QStringLiteral(
"no" );
550 return QStringLiteral(
"shape" );
552 return QStringLiteral(
"centroid_within" );
554 return QStringLiteral(
"completely_within" );
561 const QString compareString =
string.trimmed();
565 if ( compareString.compare( QLatin1String(
"no" ), Qt::CaseInsensitive ) == 0 )
567 else if ( compareString.compare( QLatin1String(
"during_render" ), Qt::CaseInsensitive ) == 0 )
569 else if ( compareString.compare( QLatin1String(
"before_render" ), Qt::CaseInsensitive ) == 0 )
582 return QStringLiteral(
"no" );
584 return QStringLiteral(
"during_render" );
586 return QStringLiteral(
"before_render" );
598 QStringList lst = str.split(
',' );
599 if ( lst.count() != 2 )
600 return QPointF( 0, 0 );
601 return QPointF( lst[0].toDouble(), lst[1].toDouble() );
612 if ( value.userType() == QMetaType::Type::QVariantList )
614 const QVariantList list = value.toList();
615 if ( list.size() != 2 )
619 bool convertOk =
false;
620 const double x = list.at( 0 ).toDouble( &convertOk );
623 const double y = list.at( 1 ).toDouble( &convertOk );
628 return QPointF( x, y );
636 const QStringList list = value.toString().trimmed().split(
',' );
637 if ( list.count() != 2 )
639 bool convertOk =
false;
640 const double x = list.at( 0 ).toDouble( &convertOk );
643 const double y = list.at( 1 ).toDouble( &convertOk );
648 return QPointF( x, y );
662 QStringList lst =
string.split(
',' );
663 if ( lst.count() != 2 )
664 return QSizeF( 0, 0 );
665 return QSizeF( lst[0].toDouble(), lst[1].toDouble() );
676 if ( value.userType() == QMetaType::Type::QVariantList )
678 const QVariantList list = value.toList();
679 if ( list.size() != 2 )
683 bool convertOk =
false;
684 const double x = list.at( 0 ).toDouble( &convertOk );
687 const double y = list.at( 1 ).toDouble( &convertOk );
692 return QSizeF( x, y );
700 const QStringList list = value.toString().trimmed().split(
',' );
701 if ( list.count() != 2 )
703 bool convertOk =
false;
704 const double x = list.at( 0 ).toDouble( &convertOk );
707 const double y = list.at( 1 ).toDouble( &convertOk );
712 return QSizeF( x, y );
733 if ( str.startsWith( QLatin1String(
"3x:" ) ) )
736 const QString chopped = str.mid( 3 );
737 lst = chopped.split(
',' );
741 lst = str.split(
',' );
743 if ( lst.count() < 2 )
746 double minScale = lst[0].toDouble();
748 minScale = minScale != 0 ? 1.0 / minScale : 0;
749 double maxScale = lst[1].toDouble();
751 maxScale = maxScale != 0 ? 1.0 / maxScale : 0;
753 if ( lst.count() < 6 )
773 *scaleFactor = 0.001;
774 return QStringLiteral(
"http://www.opengeospatial.org/se/units/metre" );
779 return QStringLiteral(
"http://www.opengeospatial.org/se/units/metre" );
786 *scaleFactor = 1 / 0.28;
795 if ( str == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
801 else if ( str == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
804 *scaleFactor = 0.3048;
819 QString vectorString;
820 QVector<qreal>::const_iterator it = v.constBegin();
821 for ( ; it != v.constEnd(); ++it )
823 if ( it != v.constBegin() )
825 vectorString.append(
';' );
827 vectorString.append( QString::number( *it ) );
834 QVector<qreal> resultVector;
836 const QStringList realList = s.split(
';' );
837 QStringList::const_iterator it = realList.constBegin();
838 for ( ; it != realList.constEnd(); ++it )
840 resultVector.append( it->toDouble() );
848 QString vectorString;
849 QVector<qreal>::const_iterator it = v.constBegin();
850 for ( ; it != v.constEnd(); ++it )
852 if ( it != v.constBegin() )
854 vectorString.append(
' ' );
856 vectorString.append( QString::number( *it ) );
863 QVector<qreal> resultVector;
865 const QStringList realList = s.split(
' ' );
866 QStringList::const_iterator it = realList.constBegin();
867 for ( ; it != realList.constEnd(); ++it )
869 resultVector.append( it->toDouble() );
877 QString encodedValue;
879 switch ( scaleMethod )
882 encodedValue = QStringLiteral(
"diameter" );
885 encodedValue = QStringLiteral(
"area" );
895 if ( str == QLatin1String(
"diameter" ) )
909 if ( s.compare( QLatin1String(
"Lighten" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Lighten;
910 if ( s.compare( QLatin1String(
"Screen" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Screen;
911 if ( s.compare( QLatin1String(
"Dodge" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorDodge;
912 if ( s.compare( QLatin1String(
"Addition" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Plus;
913 if ( s.compare( QLatin1String(
"Darken" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Darken;
914 if ( s.compare( QLatin1String(
"Multiply" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Multiply;
915 if ( s.compare( QLatin1String(
"Burn" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorBurn;
916 if ( s.compare( QLatin1String(
"Overlay" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Overlay;
917 if ( s.compare( QLatin1String(
"SoftLight" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_SoftLight;
918 if ( s.compare( QLatin1String(
"HardLight" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_HardLight;
919 if ( s.compare( QLatin1String(
"Difference" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Difference;
920 if ( s.compare( QLatin1String(
"Subtract" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Exclusion;
921 return QPainter::CompositionMode_SourceOver;
926 return QIcon(
symbolPreviewPixmap( symbol, size, padding,
nullptr,
false,
nullptr, shape, screen ) );
934 QPixmap pixmap( size * devicePixelRatio );
935 pixmap.setDevicePixelRatio( devicePixelRatio );
937 pixmap.fill( Qt::transparent );
939 painter.begin( &pixmap );
944 painter.setRenderHint( QPainter::Antialiasing );
945 painter.setRenderHint( QPainter::SmoothPixmapTransform );
955 size.setWidth( size.rwidth() - ( padding * 2 ) );
956 size.setHeight( size.rheight() - ( padding * 2 ) );
957 painter.translate( padding, padding );
967 std::unique_ptr<QgsSymbol> symbol_noDD( symbol->
clone( ) );
969 for (
const auto &layer : layers )
971 for (
int i = 0; i < layer->dataDefinedProperties().count(); ++i )
973 QgsProperty &prop = layer->dataDefinedProperties().property( i );
979 symbol_noDD->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape, screen );
983 std::unique_ptr<QgsSymbol> symbolClone( symbol->
clone( ) );
984 symbolClone->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape, screen );
998 maxBleed = layerMaxBleed > maxBleed ? layerMaxBleed : maxBleed;
1008 painter.begin( &picture );
1009 painter.setRenderHint( QPainter::Antialiasing );
1019 switch ( parentSymbolType )
1034 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
1035 layerClone->drawPreviewIcon( symbolContext, size );
1043 QPixmap pixmap( size * devicePixelRatio );
1044 pixmap.setDevicePixelRatio( devicePixelRatio );
1045 pixmap.fill( Qt::transparent );
1047 painter.begin( &pixmap );
1048 painter.setRenderHint( QPainter::Antialiasing );
1066 switch ( parentSymbolType )
1081 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
1082 layerClone->drawPreviewIcon( symbolContext, size );
1084 return QIcon( pixmap );
1094 QPixmap pixmap( size );
1095 pixmap.fill( Qt::transparent );
1098 painter.begin( &pixmap );
1101 if ( drawTransparentBackground )
1102 drawStippledBackground( &painter, QRect( padding, padding, size.width() - padding * 2, size.height() - padding * 2 ) );
1106 switch ( direction )
1108 case Qt::Horizontal:
1110 for (
int i = 0; i < size.width(); i++ )
1112 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.width() ) );
1113 painter.setPen( pen );
1114 const int x = flipDirection ? size.width() - i - 1 : i;
1115 painter.drawLine( x, 0 + padding, x, size.height() - 1 - padding );
1122 for (
int i = 0; i < size.height(); i++ )
1124 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.height() ) );
1125 painter.setPen( pen );
1126 const int y = flipDirection ? size.height() - i - 1 : i;
1127 painter.drawLine( 0 + padding, y, size.width() - 1 - padding, y );
1140 uchar pixDataRGB[] = { 255, 255, 255, 255,
1145 const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
1147 const int width = ( rect.width() < rect.height() ) ?
1148 rect.width() / 2.5 : rect.height() / 2.5;
1149 const QPixmap pix = QPixmap::fromImage( img.scaled( width, width ) );
1152 brush.setTexture( pix );
1153 painter->fillRect( rect, brush );
1158 const qreal s = ( markerSize - 1 ) / 2.0;
1163 p.setPen( QColor( 50, 100, 120, 200 ) );
1164 p.setBrush( QColor( 200, 200, 210, 120 ) );
1165 p.drawEllipse( x - s, y - s, s * 2, s * 2 );
1168 p.setPen( QColor( 255, 0, 0 ) );
1169 p.drawLine( x - s, y + s, x + s, y - s );
1170 p.drawLine( x - s, y - s, x + s, y + s );
1182static QPolygonF makeOffsetGeometry(
const QgsPolylineXY &polyline )
1184 int i, pointCount = polyline.count();
1186 QPolygonF resultLine;
1187 resultLine.resize( pointCount );
1191 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1192 resultLine[i] = QPointF( tempPtr->
x(), tempPtr->
y() );
1196static QList<QPolygonF> makeOffsetGeometry(
const QgsPolygonXY &polygon )
1198 QList<QPolygonF> resultGeom;
1199 resultGeom.reserve( polygon.size() );
1200 for (
int ring = 0; ring < polygon.size(); ++ring )
1201 resultGeom.append( makeOffsetGeometry( polygon[ ring ] ) );
1207 QList<QPolygonF> resultLine;
1209 if ( polyline.count() < 2 )
1211 resultLine.append( polyline );
1215 unsigned int i, pointCount = polyline.count();
1218 QPointF *tempPtr = polyline.data();
1219 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1220 tempPolyline[i] =
QgsPointXY( tempPtr->rx(), tempPtr->ry() );
1223 if ( !tempGeometry.
isNull() )
1225 const int quadSegments = 0;
1226 const double miterLimit = 2.0;
1234 if ( !offsetGeom.
isNull() )
1236 tempGeometry = offsetGeom;
1241 resultLine.append( makeOffsetGeometry( line ) );
1246 resultLine.append( makeOffsetGeometry( tempGeometry.
asPolygon() ) );
1252 resultLine.reserve( tempMPolyline.count() );
1253 for (
int part = 0; part < tempMPolyline.count(); ++part )
1255 resultLine.append( makeOffsetGeometry( tempMPolyline[ part ] ) );
1262 resultLine.reserve( tempMPolygon.count() );
1263 for (
int part = 0; part < tempMPolygon.count(); ++part )
1265 resultLine.append( makeOffsetGeometry( tempMPolygon[ part ] ) );
1273 resultLine.append( polyline );
1282 if ( element.isNull() )
1286 QDomNode layerNode = element.firstChild();
1288 while ( !layerNode.isNull() )
1290 QDomElement e = layerNode.toElement();
1291 if ( !e.isNull() && e.tagName() != QLatin1String(
"data_defined_properties" ) && e.tagName() != QLatin1String(
"buffer" ) )
1293 if ( e.tagName() != QLatin1String(
"layer" ) )
1302 const QDomElement s = e.firstChildElement( QStringLiteral(
"symbol" ) );
1305 std::unique_ptr< QgsSymbol > subSymbol(
loadSymbol( s, context ) );
1312 layers.append( layer );
1314 for (
int i = 0; i < subSymbol->symbolLayerCount(); ++i )
1316 layers.append( subSymbol->symbolLayer( i )->clone() );
1321 const bool res = layer->setSubSymbol( subSymbol.release() );
1324 QgsDebugError( QStringLiteral(
"symbol layer refused subsymbol: " ) + s.attribute(
"name" ) );
1326 layers.append( layer );
1331 layers.append( layer );
1336 layerNode = layerNode.nextSibling();
1339 if ( layers.isEmpty() )
1345 const QString symbolType = element.attribute( QStringLiteral(
"type" ) );
1348 if ( symbolType == QLatin1String(
"line" ) )
1350 else if ( symbolType == QLatin1String(
"fill" ) )
1352 else if ( symbolType == QLatin1String(
"marker" ) )
1360 if ( element.hasAttribute( QStringLiteral(
"outputUnit" ) ) )
1364 if ( element.hasAttribute( ( QStringLiteral(
"mapUnitScale" ) ) ) )
1367 const double oldMin = element.attribute( QStringLiteral(
"mapUnitMinScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1368 mapUnitScale.
minScale = oldMin != 0 ? 1.0 / oldMin : 0;
1369 const double oldMax = element.attribute( QStringLiteral(
"mapUnitMaxScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1370 mapUnitScale.
maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
1373 symbol->
setOpacity( element.attribute( QStringLiteral(
"alpha" ), QStringLiteral(
"1.0" ) ).toDouble() );
1374 symbol->
setExtentBuffer( element.attribute( QStringLiteral(
"extent_buffer" ), QStringLiteral(
"0.0" ) ).toDouble() );
1376 symbol->
setClipFeaturesToExtent( element.attribute( QStringLiteral(
"clip_to_extent" ), QStringLiteral(
"1" ) ).toInt() );
1377 symbol->
setForceRHR( element.attribute( QStringLiteral(
"force_rhr" ), QStringLiteral(
"0" ) ).toInt() );
1379 if ( element.attribute( QStringLiteral(
"renderer_should_use_levels" ), QStringLiteral(
"0" ) ).toInt() )
1386 if ( !element.firstChildElement( QStringLiteral(
"buffer" ) ).isNull() )
1388 auto bufferSettings = std::make_unique< QgsSymbolBufferSettings >();
1389 bufferSettings->readXml( element, context );
1397 const QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1398 if ( !ddProps.isNull() )
1408 const QString layerClass = element.attribute( QStringLiteral(
"class" ) );
1409 const bool locked = element.attribute( QStringLiteral(
"locked" ) ).toInt();
1410 const bool enabled = element.attribute( QStringLiteral(
"enabled" ), QStringLiteral(
"1" ) ).toInt();
1411 const int pass = element.attribute( QStringLiteral(
"pass" ) ).toInt();
1412 const QString
id = element.attribute( QStringLiteral(
"id" ) );
1433 if ( !
id.isEmpty() )
1437 const QDomElement effectElem = element.firstChildElement( QStringLiteral(
"effect" ) );
1438 if ( !effectElem.isNull() )
1446 const QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1447 if ( !ddProps.isNull() )
1454 const QSet< int > oldKeys = prevProperties.
propertyKeys();
1455 for (
int key : oldKeys )
1476 return QStringLiteral(
"line" );
1478 return QStringLiteral(
"marker" );
1480 return QStringLiteral(
"fill" );
1489 QDomElement symEl = doc.createElement( QStringLiteral(
"symbol" ) );
1490 symEl.setAttribute( QStringLiteral(
"type" ), _nameForSymbolType( symbol->
type() ) );
1491 symEl.setAttribute( QStringLiteral(
"name" ), name );
1492 symEl.setAttribute( QStringLiteral(
"alpha" ), QString::number( symbol->
opacity() ) );
1493 symEl.setAttribute( QStringLiteral(
"clip_to_extent" ), symbol->
clipFeaturesToExtent() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1496 symEl.setAttribute( QStringLiteral(
"extent_buffer" ), QString::number( symbol->
extentBuffer() ) );
1499 symEl.setAttribute( QStringLiteral(
"force_rhr" ), symbol->
forceRHR() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1501 symEl.setAttribute( QStringLiteral(
"renderer_should_use_levels" ), QStringLiteral(
"1" ) );
1503 symEl.setAttribute( QStringLiteral(
"is_animated" ), symbol->
animationSettings().
isAnimated() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1507 bufferSettings->writeXml( symEl, context );
1511 QDomElement ddProps = doc.createElement( QStringLiteral(
"data_defined_properties" ) );
1513 symEl.appendChild( ddProps );
1519 QDomElement layerEl = doc.createElement( QStringLiteral(
"layer" ) );
1520 layerEl.setAttribute( QStringLiteral(
"class" ), layer->
layerType() );
1521 layerEl.setAttribute( QStringLiteral(
"enabled" ), layer->
enabled() );
1522 layerEl.setAttribute( QStringLiteral(
"locked" ), layer->
isLocked() );
1523 layerEl.setAttribute( QStringLiteral(
"pass" ), layer->
renderingPass() );
1524 layerEl.setAttribute( QStringLiteral(
"id" ), layer->
id() );
1538 QDomElement ddProps = doc.createElement( QStringLiteral(
"data_defined_properties" ) );
1540 layerEl.appendChild( ddProps );
1544 const QString subname = QStringLiteral(
"@%1@%2" ).arg( name ).arg( i );
1545 const QDomElement subEl =
saveSymbol( subname, subSymbol, doc, context );
1546 layerEl.appendChild( subEl );
1548 symEl.appendChild( layerEl );
1556 QDomDocument doc( QStringLiteral(
"qgis-symbol-definition" ) );
1559 QTextStream stream( &props );
1560 symbolElem.save( stream, -1 );
1566 QList<QgsSymbolLayer *> &layers )
1570 if ( element.isNull() )
1575 const QString symbolizerName = element.localName();
1577 if ( symbolizerName == QLatin1String(
"PointSymbolizer" ) )
1580 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1581 if ( graphicElem.isNull() )
1583 QgsDebugError( QStringLiteral(
"Graphic element not found in PointSymbolizer" ) );
1619 if ( symbolizerName == QLatin1String(
"LineSymbolizer" ) )
1622 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1623 if ( strokeElem.isNull() )
1625 QgsDebugError( QStringLiteral(
"Stroke element not found in LineSymbolizer" ) );
1655 if ( symbolizerName == QLatin1String(
"PolygonSymbolizer" ) )
1658 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1659 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1660 if ( fillElem.isNull() && strokeElem.isNull() )
1662 QgsDebugError( QStringLiteral(
"neither Fill nor Stroke element not found in PolygonSymbolizer" ) );
1680 if ( l->
layerType() == QLatin1String(
"SimpleFill" ) || l->
layerType() == QLatin1String(
"SVGFill" ) )
1716 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1717 if ( fillElem.isNull() )
1719 QgsDebugError( QStringLiteral(
"Fill element not found" ) );
1741 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1742 if ( strokeElem.isNull() )
1744 QgsDebugError( QStringLiteral(
"Stroke element not found" ) );
1760 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1761 if ( graphicElem.isNull() )
1763 QgsDebugError( QStringLiteral(
"Graphic element not found" ) );
1788 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1789 if ( graphicElem.isNull() )
1792 const QDomElement externalGraphicElem = graphicElem.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
1793 if ( externalGraphicElem.isNull() )
1797 const QDomElement formatElem = externalGraphicElem.firstChildElement( QStringLiteral(
"Format" ) );
1798 if ( formatElem.isNull() )
1801 const QString elementFormat = formatElem.firstChild().nodeValue();
1802 if ( ! format.isEmpty() && elementFormat != format )
1804 QgsDebugMsgLevel(
"unsupported External Graphic format found: " + elementFormat, 4 );
1809 const QDomElement onlineResourceElem = externalGraphicElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1810 const QDomElement inlineContentElem = externalGraphicElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1811 if ( !onlineResourceElem.isNull() )
1816 else if ( !inlineContentElem.isNull() )
1829 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1830 if ( graphicElem.isNull() )
1833 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1834 if ( markElem.isNull() )
1837 const QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
1838 return !wellKnownNameElem.isNull();
1844 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1845 if ( graphicElem.isNull() )
1848 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1849 if ( markElem.isNull() )
1853 const QDomElement formatElem = markElem.firstChildElement( QStringLiteral(
"Format" ) );
1854 if ( formatElem.isNull() )
1857 const QString format = formatElem.firstChild().nodeValue();
1858 if ( format != QLatin1String(
"ttf" ) )
1860 QgsDebugError(
"unsupported Graphic Mark format found: " + format );
1865 const QDomElement onlineResourceElem = markElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1866 const QDomElement inlineContentElem = markElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1867 if ( !onlineResourceElem.isNull() )
1870 const QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
1871 if ( !markIndexElem.isNull() )
1874 else if ( !inlineContentElem.isNull() )
1889 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1890 if ( graphicElem.isNull() )
1894 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
1896 if ( it.key() == QLatin1String(
"widthHeightFactor" ) )
1907 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1908 if ( strokeElem.isNull() )
1911 QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral(
"GraphicStroke" ) );
1912 if ( graphicStrokeElem.isNull() )
1920 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1921 if ( fillElem.isNull() )
1924 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1925 if ( graphicFillElem.isNull() )
1928 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1929 if ( graphicElem.isNull() )
1935 QColor fillColor, strokeColor;
1936 double size, strokeWidth;
1937 Qt::PenStyle strokeStyle;
1938 if ( !
wellKnownMarkerFromSld( graphicElem, name, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
1941 if ( name != QLatin1String(
"horline" ) )
1949 const double angle = angleFunc.toDouble( &ok );
1955 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1956 if ( fillElem.isNull() )
1959 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1960 if ( graphicFillElem.isNull() )
1963 const QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1964 if ( graphicElem.isNull() )
1967 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1968 if ( markElem.isNull() )
1976 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1977 if ( fillElem.isNull() )
1980 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1981 if ( graphicFillElem.isNull() )
1989 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1990 if ( fillElem.isNull() )
1993 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1994 if ( graphicFillElem.isNull() )
2014 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
2015 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
2019 bool validFill =
false, validStroke =
false;
2024 Qt::BrushStyle fillStyle;
2026 if (
fillFromSld( fillElem, fillStyle, fillColor ) )
2032 Qt::PenStyle strokeStyle;
2033 double strokeWidth = 1.0, dashOffset = 0.0;
2034 QVector<qreal> customDashPattern;
2036 if (
lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth,
2037 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2040 if ( validFill || validStroke )
2043 map[QStringLiteral(
"name" )] = QStringLiteral(
"square" );
2046 map[QStringLiteral(
"size" )] = QString::number( 6 );
2047 map[QStringLiteral(
"angle" )] = QString::number( 0 );
2048 map[QStringLiteral(
"offset" )] =
encodePoint( QPointF( 0, 0 ) );
2055 bool validFill =
false, validStroke =
false;
2058 QString name, format;
2060 QColor fillColor, strokeColor;
2061 double strokeWidth = 1.0, size = 0.0, angle = 0.0;
2065 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
2066 if ( !graphicFillElem.isNull() )
2069 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
2070 if ( !graphicElem.isNull() )
2076 const QDomElement graphicChildElem = graphicElem.firstChildElement();
2077 while ( !graphicChildElem.isNull() )
2079 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2082 const QDomElement wellKnownNameElem = graphicChildElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
2083 if ( !wellKnownNameElem.isNull() )
2085 name = wellKnownNameElem.firstChild().nodeValue();
2091 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) || graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2094 const QDomElement formatElem = graphicChildElem.firstChildElement( QStringLiteral(
"Format" ) );
2095 if ( formatElem.isNull() )
2098 format = formatElem.firstChild().nodeValue();
2102 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) && format != QLatin1String(
"image/svg+xml" ) )
2107 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format != QLatin1String(
"ttf" ) )
2111 const QDomElement onlineResourceElem = graphicChildElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
2112 const QDomElement inlineContentElem = graphicChildElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
2114 if ( !onlineResourceElem.isNull() )
2116 name = onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) );
2118 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format == QLatin1String(
"ttf" ) )
2121 if ( name.startsWith( QLatin1String(
"ttf://" ) ) )
2122 name = name.mid( 6 );
2125 const QDomElement markIndexElem = graphicChildElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
2126 if ( markIndexElem.isNull() )
2130 const int v = markIndexElem.firstChild().nodeValue().toInt( &ok );
2141 else if ( !inlineContentElem.isNull() )
2151 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2153 name = QStringLiteral(
"square" );
2160 if ( found && graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2167 Qt::BrushStyle markFillStyle;
2169 QDomElement markFillElem = graphicChildElem.firstChildElement( QStringLiteral(
"Fill" ) );
2170 if (
fillFromSld( markFillElem, markFillStyle, fillColor ) )
2175 Qt::PenStyle strokeStyle;
2176 double strokeWidth = 1.0, dashOffset = 0.0;
2177 QVector<qreal> customDashPattern;
2179 QDomElement markStrokeElem = graphicChildElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2180 if (
lineFromSld( markStrokeElem, strokeStyle, strokeColor, strokeWidth,
2181 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2188 const QDomElement opacityElem = graphicElem.firstChildElement( QStringLiteral(
"Opacity" ) );
2189 if ( !opacityElem.isNull() )
2190 fillColor.setAlpha(
decodeSldAlpha( opacityElem.firstChild().nodeValue() ) );
2192 const QDomElement sizeElem = graphicElem.firstChildElement( QStringLiteral(
"Size" ) );
2193 if ( !sizeElem.isNull() )
2196 const double v = sizeElem.firstChild().nodeValue().toDouble( &ok );
2205 const double v = angleFunc.toDouble( &ok );
2215 if ( validFill || validStroke )
2217 if ( format == QLatin1String(
"image/svg+xml" ) )
2220 map[QStringLiteral(
"name" )] = name;
2221 map[QStringLiteral(
"fill" )] = fillColor.name();
2222 map[QStringLiteral(
"outline" )] = strokeColor.name();
2223 map[QStringLiteral(
"outline-width" )] = QString::number( strokeWidth );
2225 map[QStringLiteral(
"size" )] = QString::number( size );
2227 map[QStringLiteral(
"angle" )] = QString::number( angle );
2228 if ( !offset.isNull() )
2229 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
2232 else if ( format == QLatin1String(
"ttf" ) )
2235 map[QStringLiteral(
"font" )] = name;
2236 map[QStringLiteral(
"chr" )] = markIndex;
2239 map[QStringLiteral(
"size" )] = QString::number( size );
2241 map[QStringLiteral(
"angle" )] = QString::number( angle );
2242 if ( !offset.isNull() )
2243 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
2249 if ( layers.isEmpty() )
2252 layerList << layers;
2259 QString patternName;
2260 switch ( brushStyle )
2265 case Qt::SolidPattern:
2266 if ( color.isValid() )
2269 if ( color.alpha() < 255 )
2274 case Qt::CrossPattern:
2275 case Qt::DiagCrossPattern:
2276 case Qt::HorPattern:
2277 case Qt::VerPattern:
2278 case Qt::BDiagPattern:
2279 case Qt::FDiagPattern:
2280 case Qt::Dense1Pattern:
2281 case Qt::Dense2Pattern:
2282 case Qt::Dense3Pattern:
2283 case Qt::Dense4Pattern:
2284 case Qt::Dense5Pattern:
2285 case Qt::Dense6Pattern:
2286 case Qt::Dense7Pattern:
2291 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( brushStyle ) ) );
2295 QDomElement graphicFillElem = doc.createElement( QStringLiteral(
"se:GraphicFill" ) );
2296 element.appendChild( graphicFillElem );
2298 QDomElement graphicElem = doc.createElement( QStringLiteral(
"se:Graphic" ) );
2299 graphicFillElem.appendChild( graphicElem );
2301 const QColor fillColor = patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
2302 const QColor strokeColor = !patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
2305 wellKnownMarkerToSld( doc, graphicElem, patternName, fillColor, strokeColor, Qt::SolidLine, -1, -1 );
2312 brushStyle = Qt::SolidPattern;
2313 color = QColor( 128, 128, 128 );
2315 if ( element.isNull() )
2317 brushStyle = Qt::NoBrush;
2322 const QDomElement graphicFillElem = element.firstChildElement( QStringLiteral(
"GraphicFill" ) );
2324 if ( graphicFillElem.isNull() )
2327 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2329 QgsDebugMsgLevel( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ), 2 );
2331 if ( it.key() == QLatin1String(
"fill" ) )
2332 color = QColor( it.value() );
2333 else if ( it.key() == QLatin1String(
"fill-opacity" ) )
2339 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
2340 if ( graphicElem.isNull() )
2343 QString patternName = QStringLiteral(
"square" );
2344 QColor fillColor, strokeColor;
2345 double strokeWidth, size;
2346 Qt::PenStyle strokeStyle;
2347 if ( !
wellKnownMarkerFromSld( graphicElem, patternName, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
2351 if ( brushStyle == Qt::NoBrush )
2354 const QColor
c = patternName.startsWith( QLatin1String(
"brush://" ) ) ? fillColor : strokeColor;
2363 Qt::PenStyle penStyle,
const QColor &color,
double width,
2364 const Qt::PenJoinStyle *penJoinStyle,
const Qt::PenCapStyle *penCapStyle,
2365 const QVector<qreal> *customDashPattern,
double dashOffset )
2367 QVector<qreal> dashPattern;
2368 const QVector<qreal> *pattern = &dashPattern;
2370 if ( penStyle == Qt::CustomDashLine && !customDashPattern )
2372 element.appendChild( doc.createComment( QStringLiteral(
"WARNING: Custom dash pattern required but not provided. Using default dash pattern." ) ) );
2373 penStyle = Qt::DashLine;
2385 dashPattern.push_back( 4.0 );
2386 dashPattern.push_back( 2.0 );
2389 dashPattern.push_back( 1.0 );
2390 dashPattern.push_back( 2.0 );
2392 case Qt::DashDotLine:
2393 dashPattern.push_back( 4.0 );
2394 dashPattern.push_back( 2.0 );
2395 dashPattern.push_back( 1.0 );
2396 dashPattern.push_back( 2.0 );
2398 case Qt::DashDotDotLine:
2399 dashPattern.push_back( 4.0 );
2400 dashPattern.push_back( 2.0 );
2401 dashPattern.push_back( 1.0 );
2402 dashPattern.push_back( 2.0 );
2403 dashPattern.push_back( 1.0 );
2404 dashPattern.push_back( 2.0 );
2407 case Qt::CustomDashLine:
2408 Q_ASSERT( customDashPattern );
2409 pattern = customDashPattern;
2413 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( penStyle ) ) );
2417 if ( color.isValid() )
2420 if ( color.alpha() < 255 )
2427 else if ( width == 0 )
2437 if ( !pattern->isEmpty() )
2447 Qt::PenStyle &penStyle, QColor &color,
double &width,
2448 Qt::PenJoinStyle *penJoinStyle, Qt::PenCapStyle *penCapStyle,
2449 QVector<qreal> *customDashPattern,
double *dashOffset )
2453 penStyle = Qt::SolidLine;
2454 color = QColor( 0, 0, 0 );
2457 *penJoinStyle = Qt::BevelJoin;
2459 *penCapStyle = Qt::SquareCap;
2460 if ( customDashPattern )
2461 customDashPattern->clear();
2465 if ( element.isNull() )
2467 penStyle = Qt::NoPen;
2473 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2475 QgsDebugMsgLevel( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ), 2 );
2477 if ( it.key() == QLatin1String(
"stroke" ) )
2479 color = QColor( it.value() );
2481 else if ( it.key() == QLatin1String(
"stroke-opacity" ) )
2485 else if ( it.key() == QLatin1String(
"stroke-width" ) )
2488 const double w = it.value().toDouble( &ok );
2492 else if ( it.key() == QLatin1String(
"stroke-linejoin" ) && penJoinStyle )
2496 else if ( it.key() == QLatin1String(
"stroke-linecap" ) && penCapStyle )
2500 else if ( it.key() == QLatin1String(
"stroke-dasharray" ) )
2503 if ( !dashPattern.isEmpty() )
2507 bool dashPatternFound =
false;
2509 if ( dashPattern.count() == 2 )
2511 if ( dashPattern.at( 0 ) == 4.0 &&
2512 dashPattern.at( 1 ) == 2.0 )
2514 penStyle = Qt::DashLine;
2515 dashPatternFound =
true;
2517 else if ( dashPattern.at( 0 ) == 1.0 &&
2518 dashPattern.at( 1 ) == 2.0 )
2520 penStyle = Qt::DotLine;
2521 dashPatternFound =
true;
2524 else if ( dashPattern.count() == 4 )
2526 if ( dashPattern.at( 0 ) == 4.0 &&
2527 dashPattern.at( 1 ) == 2.0 &&
2528 dashPattern.at( 2 ) == 1.0 &&
2529 dashPattern.at( 3 ) == 2.0 )
2531 penStyle = Qt::DashDotLine;
2532 dashPatternFound =
true;
2535 else if ( dashPattern.count() == 6 )
2537 if ( dashPattern.at( 0 ) == 4.0 &&
2538 dashPattern.at( 1 ) == 2.0 &&
2539 dashPattern.at( 2 ) == 1.0 &&
2540 dashPattern.at( 3 ) == 2.0 &&
2541 dashPattern.at( 4 ) == 1.0 &&
2542 dashPattern.at( 5 ) == 2.0 )
2544 penStyle = Qt::DashDotDotLine;
2545 dashPatternFound =
true;
2550 if ( !dashPatternFound )
2552 if ( customDashPattern )
2554 penStyle = Qt::CustomDashLine;
2555 *customDashPattern = dashPattern;
2559 QgsDebugMsgLevel( QStringLiteral(
"custom dash pattern required but not provided. Using default dash pattern." ), 2 );
2560 penStyle = Qt::DashLine;
2565 else if ( it.key() == QLatin1String(
"stroke-dashoffset" ) && dashOffset )
2568 const double d = it.value().toDouble( &ok );
2578 const QString &path,
const QString &mime,
2579 const QColor &color,
double size )
2581 QDomElement externalGraphicElem = doc.createElement( QStringLiteral(
"se:ExternalGraphic" ) );
2582 element.appendChild( externalGraphicElem );
2591 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2593 element.appendChild( sizeElem );
2598 const QString &path,
const QColor &fillColor,
double size,
const QColor &strokeColor,
double strokeWidth )
2605 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Parametric SVG" ) ) );
2606 const QString parametricPath =
getSvgParametricPath( path, fillColor, strokeColor, strokeWidth );
2609 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Plain SVG fallback, no parameters" ) ) );
2612 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Well known marker fallback" ) ) );
2618 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2620 graphicElem.appendChild( sizeElem );
2628 if ( fillColor.isValid() )
2630 url.addQueryItem( QStringLiteral(
"fill" ), fillColor.name() );
2631 url.addQueryItem( QStringLiteral(
"fill-opacity" ),
encodeSldAlpha( fillColor.alpha() ) );
2635 url.addQueryItem( QStringLiteral(
"fill" ), QStringLiteral(
"#000000" ) );
2636 url.addQueryItem( QStringLiteral(
"fill-opacity" ), QStringLiteral(
"1" ) );
2638 if ( strokeColor.isValid() )
2640 url.addQueryItem( QStringLiteral(
"outline" ), strokeColor.name() );
2641 url.addQueryItem( QStringLiteral(
"outline-opacity" ),
encodeSldAlpha( strokeColor.alpha() ) );
2645 url.addQueryItem( QStringLiteral(
"outline" ), QStringLiteral(
"#000000" ) );
2646 url.addQueryItem( QStringLiteral(
"outline-opacity" ), QStringLiteral(
"1" ) );
2648 url.addQueryItem( QStringLiteral(
"outline-width" ), QString::number( strokeWidth ) );
2649 const QString params = url.toString( QUrl::FullyEncoded );
2650 if ( params.isEmpty() )
2656 return basePath +
"?" + params;
2661 QString &path, QString &mime,
2662 QColor &color,
double &size )
2667 QDomElement externalGraphicElem = element.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
2668 if ( externalGraphicElem.isNull() )
2673 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2674 if ( !sizeElem.isNull() )
2677 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2686 const QString &path,
const QString &format,
int *markIndex,
2687 const QColor &color,
double size )
2689 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2690 element.appendChild( markElem );
2696 QDomElement markIndexElem = doc.createElement( QStringLiteral(
"se:MarkIndex" ) );
2697 markIndexElem.appendChild( doc.createTextNode( QString::number( *markIndex ) ) );
2698 markElem.appendChild( markIndexElem );
2702 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2703 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2704 markElem.appendChild( fillElem );
2709 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2711 element.appendChild( sizeElem );
2716 QString &path, QString &format,
int &markIndex,
2717 QColor &color,
double &size )
2725 QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2726 if ( markElem.isNull() )
2731 const QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
2732 if ( !markIndexElem.isNull() )
2735 const int i = markIndexElem.firstChild().nodeValue().toInt( &ok );
2741 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2742 Qt::BrushStyle b = Qt::SolidPattern;
2747 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2748 if ( !sizeElem.isNull() )
2751 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2760 const QString &name,
const QColor &color,
const QColor &strokeColor, Qt::PenStyle strokeStyle,
2761 double strokeWidth,
double size )
2763 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2764 element.appendChild( markElem );
2766 QDomElement wellKnownNameElem = doc.createElement( QStringLiteral(
"se:WellKnownName" ) );
2767 wellKnownNameElem.appendChild( doc.createTextNode( name ) );
2768 markElem.appendChild( wellKnownNameElem );
2771 if ( color.isValid() )
2773 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2774 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2775 markElem.appendChild( fillElem );
2779 if ( strokeColor.isValid() )
2781 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
2782 lineToSld( doc, strokeElem, strokeStyle, strokeColor, strokeWidth );
2783 markElem.appendChild( strokeElem );
2789 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2791 element.appendChild( sizeElem );
2796 QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle,
2797 double &strokeWidth,
double &size )
2801 name = QStringLiteral(
"square" );
2803 strokeColor = QColor( 0, 0, 0 );
2807 const QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2808 if ( markElem.isNull() )
2811 const QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
2812 if ( !wellKnownNameElem.isNull() )
2814 name = wellKnownNameElem.firstChild().nodeValue();
2819 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2820 Qt::BrushStyle b = Qt::SolidPattern;
2825 QDomElement strokeElem = markElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2826 lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth );
2830 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2831 if ( !sizeElem.isNull() )
2834 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2844 if ( !rotationFunc.isEmpty() )
2846 QDomElement rotationElem = doc.createElement( QStringLiteral(
"se:Rotation" ) );
2848 element.appendChild( rotationElem );
2854 QDomElement rotationElem = element.firstChildElement( QStringLiteral(
"Rotation" ) );
2855 if ( !rotationElem.isNull() )
2865 if ( !alphaFunc.isEmpty() )
2867 QDomElement opacityElem = doc.createElement( QStringLiteral(
"se:Opacity" ) );
2869 element.appendChild( opacityElem );
2875 QDomElement opacityElem = element.firstChildElement( QStringLiteral(
"Opacity" ) );
2876 if ( !opacityElem.isNull() )
2885 if ( offset.isNull() )
2888 QDomElement displacementElem = doc.createElement( QStringLiteral(
"se:Displacement" ) );
2889 element.appendChild( displacementElem );
2891 QDomElement dispXElem = doc.createElement( QStringLiteral(
"se:DisplacementX" ) );
2892 dispXElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.x(), 2 ) ) );
2894 QDomElement dispYElem = doc.createElement( QStringLiteral(
"se:DisplacementY" ) );
2895 dispYElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.y(), 2 ) ) );
2897 displacementElem.appendChild( dispXElem );
2898 displacementElem.appendChild( dispYElem );
2905 QDomElement anchorElem = doc.createElement( QStringLiteral(
"se:AnchorPoint" ) );
2906 element.appendChild( anchorElem );
2908 QDomElement anchorXElem = doc.createElement( QStringLiteral(
"se:AnchorPointX" ) );
2909 anchorXElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.x() ) ) );
2911 QDomElement anchorYElem = doc.createElement( QStringLiteral(
"se:AnchorPointY" ) );
2912 anchorYElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.y() ) ) );
2914 anchorElem.appendChild( anchorXElem );
2915 anchorElem.appendChild( anchorYElem );
2920 offset = QPointF( 0, 0 );
2922 const QDomElement displacementElem = element.firstChildElement( QStringLiteral(
"Displacement" ) );
2923 if ( displacementElem.isNull() )
2926 const QDomElement dispXElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementX" ) );
2927 if ( !dispXElem.isNull() )
2930 const double offsetX = dispXElem.firstChild().nodeValue().toDouble( &ok );
2932 offset.setX( offsetX );
2935 const QDomElement dispYElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementY" ) );
2936 if ( !dispYElem.isNull() )
2939 const double offsetY = dispYElem.firstChild().nodeValue().toDouble( &ok );
2941 offset.setY( offsetY );
2948 const QString &label,
const QFont &font,
2949 const QColor &color,
double size )
2951 QDomElement labelElem = doc.createElement( QStringLiteral(
"se:Label" ) );
2952 labelElem.appendChild( doc.createTextNode( label ) );
2953 element.appendChild( labelElem );
2955 QDomElement fontElem = doc.createElement( QStringLiteral(
"se:Font" ) );
2956 element.appendChild( fontElem );
2960 fontElem.appendChild( createSldParameterElement( doc,
"font-style",
encodeSldFontStyle( font.style() ) ) );
2961 fontElem.appendChild( createSldParameterElement( doc,
"font-weight",
encodeSldFontWeight( font.weight() ) ) );
2966 if ( color.isValid() )
2968 QDomElement fillElem = doc.createElement( QStringLiteral(
"Fill" ) );
2969 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2970 element.appendChild( fillElem );
2975 Qt::PenJoinStyle joinStyle,
2976 Qt::PenCapStyle capStyle,
2978 const QVector<qreal> *dashPattern )
2981 penStyle.append(
"PEN(" );
2982 penStyle.append(
"c:" );
2983 penStyle.append(
c.name() );
2984 penStyle.append(
",w:" );
2986 penStyle.append( QString::number( width * mmScaleFactor ) );
2987 penStyle.append(
"mm" );
2990 if ( dashPattern && !dashPattern->isEmpty() )
2992 penStyle.append(
",p:\"" );
2993 QVector<qreal>::const_iterator pIt = dashPattern->constBegin();
2994 for ( ; pIt != dashPattern->constEnd(); ++pIt )
2996 if ( pIt != dashPattern->constBegin() )
2998 penStyle.append(
' ' );
3000 penStyle.append( QString::number( *pIt * mapUnitScaleFactor ) );
3001 penStyle.append(
'g' );
3003 penStyle.append(
'\"' );
3007 penStyle.append(
",cap:" );
3011 penStyle.append(
'p' );
3014 penStyle.append(
'r' );
3018 penStyle.append(
'b' );
3022 penStyle.append(
",j:" );
3023 switch ( joinStyle )
3026 penStyle.append(
'b' );
3029 penStyle.append(
'r' );
3033 penStyle.append(
'm' );
3039 penStyle.append(
",dp:" );
3040 penStyle.append( QString::number( offset * mapUnitScaleFactor ) );
3041 penStyle.append(
'g' );
3044 penStyle.append(
')' );
3051 brushStyle.append(
"BRUSH(" );
3052 brushStyle.append(
"fc:" );
3053 brushStyle.append( fillColor.name() );
3054 brushStyle.append(
')' );
3060 if ( geomFunc.isEmpty() )
3063 QDomElement geometryElem = doc.createElement( QStringLiteral(
"Geometry" ) );
3064 element.appendChild( geometryElem );
3094 QDomElement geometryElem = element.firstChildElement( QStringLiteral(
"Geometry" ) );
3095 if ( geometryElem.isNull() )
3107 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " + function ) );
3111 if ( !filterElem.isNull() )
3112 element.appendChild( filterElem );
3120 if ( function == QLatin1String(
"ELSE" ) )
3123 element.appendChild( filterElem );
3132 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " + function ) );
3136 if ( !filterElem.isNull() )
3137 element.appendChild( filterElem );
3145 QDomElement elem = element;
3146 if ( element.tagName() != QLatin1String(
"Filter" ) )
3148 const QDomNodeList filterNodes = element.elementsByTagName( QStringLiteral(
"Filter" ) );
3149 if ( !filterNodes.isEmpty() )
3151 elem = filterNodes.at( 0 ).toElement();
3155 if ( elem.isNull() )
3180 const QString &path,
const QString &format )
3184 QDomElement onlineResourceElem = doc.createElement( QStringLiteral(
"se:OnlineResource" ) );
3185 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
3186 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:href" ), url );
3187 element.appendChild( onlineResourceElem );
3189 QDomElement formatElem = doc.createElement( QStringLiteral(
"se:Format" ) );
3190 formatElem.appendChild( doc.createTextNode( format ) );
3191 element.appendChild( formatElem );
3198 const QDomElement onlineResourceElem = element.firstChildElement( QStringLiteral(
"OnlineResource" ) );
3199 if ( onlineResourceElem.isNull() )
3202 path = QUrl::fromPercentEncoding( onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) ).toUtf8() );
3204 const QDomElement formatElem = element.firstChildElement( QStringLiteral(
"Format" ) );
3205 if ( formatElem.isNull() )
3208 format = formatElem.firstChild().nodeValue();
3215 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:SvgParameter" ) );
3216 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
3217 nodeElem.appendChild( doc.createTextNode( value ) );
3226 QDomElement paramElem = element.firstChildElement();
3227 while ( !paramElem.isNull() )
3229 if ( paramElem.localName() == QLatin1String(
"SvgParameter" ) || paramElem.localName() == QLatin1String(
"CssParameter" ) )
3231 const QString name = paramElem.attribute( QStringLiteral(
"name" ) );
3232 if ( paramElem.firstChild().nodeType() == QDomNode::TextNode )
3234 value = paramElem.firstChild().nodeValue();
3238 if ( paramElem.firstChild().nodeType() == QDomNode::ElementNode &&
3239 paramElem.firstChild().localName() == QLatin1String(
"Literal" ) )
3242 value = paramElem.firstChild().firstChild().nodeValue();
3246 QgsDebugError( QStringLiteral(
"unexpected child of %1" ).arg( paramElem.localName() ) );
3250 if ( !name.isEmpty() && !value.isEmpty() )
3251 params[ name ] = value;
3254 paramElem = paramElem.nextSiblingElement();
3262 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:VendorOption" ) );
3263 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
3264 nodeElem.appendChild( doc.createTextNode( value ) );
3272 QDomElement paramElem = element.firstChildElement( QStringLiteral(
"VendorOption" ) );
3273 while ( !paramElem.isNull() )
3275 const QString name = paramElem.attribute( QStringLiteral(
"name" ) );
3276 const QString value = paramElem.firstChild().nodeValue();
3278 if ( !name.isEmpty() && !value.isEmpty() )
3279 params[ name ] = value;
3281 paramElem = paramElem.nextSiblingElement( QStringLiteral(
"VendorOption" ) );
3291 if ( newSymbols.userType() == QMetaType::Type::QVariantMap )
3293 return newSymbols.toMap();
3300 QDomElement e = element.firstChildElement();
3301 while ( !e.isNull() )
3303 if ( e.tagName() == QLatin1String(
"prop" ) )
3305 const QString propKey = e.attribute( QStringLiteral(
"k" ) );
3306 const QString propValue = e.attribute( QStringLiteral(
"v" ) );
3307 props[propKey] = propValue;
3309 e = e.nextSiblingElement();
3326 QDomElement e = element.firstChildElement();
3328 while ( !e.isNull() )
3330 if ( e.tagName() == QLatin1String(
"symbol" ) )
3334 symbols.insert( e.attribute( QStringLiteral(
"name" ) ), symbol );
3340 e = e.nextSiblingElement();
3347 QStringList subsymbols;
3349 for ( QMap<QString, QgsSymbol *>::iterator it = symbols.begin(); it != symbols.end(); ++it )
3351 if ( it.key()[0] !=
'@' )
3355 subsymbols.append( it.key() );
3357 QStringList parts = it.key().split(
'@' );
3358 if ( parts.count() < 3 )
3360 QgsDebugError(
"found subsymbol with invalid name: " + it.key() );
3364 const QString symname = parts[1];
3365 const int symlayer = parts[2].toInt();
3367 if ( !symbols.contains( symname ) )
3369 QgsDebugError(
"subsymbol references invalid symbol: " + symname );
3377 QgsDebugError(
"subsymbol references invalid symbol layer: " + QString::number( symlayer ) );
3386 QgsDebugError(
"symbol layer refused subsymbol: " + it.key() );
3393 for (
int i = 0; i < subsymbols.count(); i++ )
3394 symbols.take( subsymbols[i] );
3401 QDomElement symbolsElem = doc.createElement( tagName );
3404 for ( QMap<QString, QgsSymbol *>::iterator its = symbols.begin(); its != symbols.end(); ++its )
3406 const QDomElement symEl =
saveSymbol( its.key(), its.value(), doc, context );
3407 symbolsElem.appendChild( symEl );
3415 qDeleteAll( symbols );
3424 std::unique_ptr< QMimeData >mimeData(
new QMimeData );
3426 QDomDocument symbolDoc;
3428 symbolDoc.appendChild( symbolElem );
3429 mimeData->setText( symbolDoc.toString() );
3432 mimeData->setColorData( symbol->
color() );
3434 return mimeData.release();
3442 const QString text = data->text();
3443 if ( !text.isEmpty() )
3448 if ( doc.setContent( text ) )
3450 elem = doc.documentElement();
3452 if ( elem.nodeName() != QLatin1String(
"symbol" ) )
3453 elem = elem.firstChildElement( QStringLiteral(
"symbol" ) );
3464 const QString rampType = element.attribute( QStringLiteral(
"type" ) );
3489 QDomElement rampEl = doc.createElement( QStringLiteral(
"colorramp" ) );
3490 rampEl.setAttribute( QStringLiteral(
"type" ), ramp->
type() );
3491 rampEl.setAttribute( QStringLiteral(
"name" ), name );
3499 QVariantMap rampMap;
3501 rampMap.insert( QStringLiteral(
"type" ), ramp->
type() );
3502 rampMap.insert( QStringLiteral(
"name" ), name );
3504 const QVariantMap properties = ramp->
properties();
3506 QVariantMap propertyMap;
3507 for (
auto property = properties.constBegin();
property != properties.constEnd(); ++property )
3509 propertyMap.insert( property.key(),
property.value() );
3512 rampMap.insert( QStringLiteral(
"properties" ), propertyMap );
3518 const QVariantMap rampMap = value.toMap();
3520 const QString rampType = rampMap.
value( QStringLiteral(
"type" ) ).toString();
3523 const QVariantMap propertyMap = rampMap.value( QStringLiteral(
"properties" ) ).toMap();
3526 for (
auto property = propertyMap.constBegin();
property != propertyMap.constEnd(); ++property )
3528 props.insert( property.key(),
property.value().toString() );
3550 if ( !color.isValid() )
3557 return color.name();
3562 QList<QColor> colors;
3565 const thread_local QRegularExpression sepCommaSpaceRegExp(
"(,|\\s)" );
3566 QStringList components = colorStr.simplified().split( sepCommaSpaceRegExp );
3567 QStringList::iterator it = components.begin();
3568 for ( ; it != components.end(); ++it )
3570 const QColor result =
parseColor( *it,
true );
3571 if ( result.isValid() )
3576 if ( colors.length() > 0 )
3582 const thread_local QRegularExpression sepCommaRegExp(
"(,|\n)" );
3583 components = colorStr.split( sepCommaRegExp );
3584 it = components.begin();
3585 for ( ; it != components.end(); ++it )
3587 const QColor result =
parseColor( *it,
true );
3588 if ( result.isValid() )
3593 if ( colors.length() > 0 )
3599 components = colorStr.simplified().split( QString(
' ' ) );
3600 it = components.begin();
3601 for ( ; it != components.end(); ++it )
3603 const QColor result =
parseColor( *it,
true );
3604 if ( result.isValid() )
3609 if ( colors.length() > 0 )
3615 components = colorStr.split(
'\n' );
3616 it = components.begin();
3617 for ( ; it != components.end(); ++it )
3619 const QColor result =
parseColor( *it,
true );
3620 if ( result.isValid() )
3633 QMimeData *mimeData =
new QMimeData;
3634 mimeData->setColorData( QVariant( color ) );
3635 mimeData->setText( color.name() );
3642 if ( mimeData->hasColor() )
3644 QColor mimeColor = mimeData->colorData().value<QColor>();
3645 if ( mimeColor.isValid() )
3653 if ( mimeData->hasText() )
3657 if ( textColor.isValid() )
3672 if ( data->hasFormat( QStringLiteral(
"text/xml" ) ) )
3675 const QByteArray encodedData = data->data( QStringLiteral(
"text/xml" ) );
3676 QDomDocument xmlDoc;
3677 xmlDoc.setContent( encodedData );
3679 const QDomElement dragDataElem = xmlDoc.documentElement();
3680 if ( dragDataElem.tagName() == QLatin1String(
"ColorSchemeModelDragData" ) )
3682 const QDomNodeList nodeList = dragDataElem.childNodes();
3683 const int nChildNodes = nodeList.size();
3684 QDomElement currentElem;
3686 for (
int i = 0; i < nChildNodes; ++i )
3688 currentElem = nodeList.at( i ).toElement();
3689 if ( currentElem.isNull() )
3694 QPair< QColor, QString> namedColor;
3696 namedColor.second = currentElem.attribute( QStringLiteral(
"label" ), QString() );
3698 mimeColors << namedColor;
3703 if ( mimeColors.length() == 0 && data->hasFormat( QStringLiteral(
"application/x-colorobject-list" ) ) )
3706 const QByteArray encodedData = data->data( QStringLiteral(
"application/x-colorobject-list" ) );
3707 QDomDocument xmlDoc;
3708 xmlDoc.setContent( encodedData );
3710 const QDomNodeList colorsNodes = xmlDoc.elementsByTagName( QStringLiteral(
"colors" ) );
3711 if ( colorsNodes.length() > 0 )
3713 const QDomElement colorsElem = colorsNodes.at( 0 ).toElement();
3714 const QDomNodeList colorNodeList = colorsElem.childNodes();
3715 const int nChildNodes = colorNodeList.size();
3716 QDomElement currentElem;
3718 for (
int i = 0; i < nChildNodes; ++i )
3721 currentElem = colorNodeList.at( i ).toElement();
3722 if ( currentElem.isNull() )
3727 const QDomNodeList colorNodes = currentElem.elementsByTagName( QStringLiteral(
"color" ) );
3728 const QDomNodeList nameNodes = currentElem.elementsByTagName( QStringLiteral(
"name" ) );
3730 if ( colorNodes.length() > 0 )
3732 const QDomElement colorElem = colorNodes.at( 0 ).toElement();
3734 const QStringList colorParts = colorElem.text().simplified().split(
' ' );
3735 if ( colorParts.length() < 3 )
3740 const int red = colorParts.at( 0 ).toDouble() * 255;
3741 const int green = colorParts.at( 1 ).toDouble() * 255;
3742 const int blue = colorParts.at( 2 ).toDouble() * 255;
3743 QPair< QColor, QString> namedColor;
3744 namedColor.first = QColor( red, green, blue );
3745 if ( nameNodes.length() > 0 )
3747 const QDomElement nameElem = nameNodes.at( 0 ).toElement();
3748 namedColor.second = nameElem.text();
3750 mimeColors << namedColor;
3756 if ( mimeColors.length() == 0 && data->hasText() )
3760 QList< QColor >::iterator it = parsedColors.begin();
3761 for ( ; it != parsedColors.end(); ++it )
3763 mimeColors << qMakePair( *it, QString() );
3767 if ( mimeColors.length() == 0 && data->hasColor() )
3770 const QColor mimeColor = data->colorData().value<QColor>();
3771 if ( mimeColor.isValid() )
3773 mimeColors << qMakePair( mimeColor, QString() );
3783 QMimeData *mimeData =
new QMimeData();
3784 QDomDocument xmlDoc;
3785 QDomElement xmlRootElement = xmlDoc.createElement( QStringLiteral(
"ColorSchemeModelDragData" ) );
3786 xmlDoc.appendChild( xmlRootElement );
3788 QgsNamedColorList::const_iterator colorIt = colorList.constBegin();
3789 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3791 QDomElement namedColor = xmlDoc.createElement( QStringLiteral(
"NamedColor" ) );
3793 namedColor.setAttribute( QStringLiteral(
"label" ), ( *colorIt ).second );
3794 xmlRootElement.appendChild( namedColor );
3796 mimeData->setData( QStringLiteral(
"text/xml" ), xmlDoc.toByteArray() );
3804 colorIt = colorList.constBegin();
3805 QStringList colorListString;
3806 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3808 colorListString << ( *colorIt ).first.name();
3810 mimeData->setText( colorListString.join( QLatin1Char(
'\n' ) ) );
3813 if ( colorList.length() > 0 )
3815 mimeData->setColorData( QVariant( colorList.at( 0 ).first ) );
3823 if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3828 QTextStream stream( &file );
3829#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
3830 stream.setCodec(
"UTF-8" );
3833 stream <<
"GIMP Palette" << Qt::endl;
3834 if ( paletteName.isEmpty() )
3836 stream <<
"Name: QGIS Palette" << Qt::endl;
3840 stream <<
"Name: " << paletteName << Qt::endl;
3842 stream <<
"Columns: 4" << Qt::endl;
3843 stream <<
'#' << Qt::endl;
3845 for ( QgsNamedColorList::ConstIterator colorIt = colors.constBegin(); colorIt != colors.constEnd(); ++colorIt )
3847 const QColor color = ( *colorIt ).first;
3848 if ( !color.isValid() )
3852 stream << QStringLiteral(
"%1 %2 %3" ).arg( color.red(), 3 ).arg( color.green(), 3 ).arg( color.blue(), 3 );
3853 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << Qt::endl;
3864 if ( !file.open( QIODevice::ReadOnly ) )
3867 return importedColors;
3870 QTextStream in( &file );
3871#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
3872 in.setCodec(
"UTF-8" );
3875 QString line = in.readLine();
3876 if ( !line.startsWith( QLatin1String(
"GIMP Palette" ) ) )
3879 return importedColors;
3883 while ( !in.atEnd() && !line.startsWith( QLatin1String(
"Name:" ) ) && !line.startsWith(
'#' ) )
3885 line = in.readLine();
3887 if ( line.startsWith( QLatin1String(
"Name:" ) ) )
3889 const thread_local QRegularExpression nameRx(
"Name:\\s*(\\S.*)$" );
3890 const QRegularExpressionMatch match = nameRx.match( line );
3891 if ( match.hasMatch() )
3893 name = match.captured( 1 );
3898 while ( !in.atEnd() && !line.startsWith(
'#' ) )
3900 line = in.readLine();
3905 return importedColors;
3909 const thread_local QRegularExpression rx(
"^\\s*(\\d+)\\s+(\\d+)\\s+(\\d+)(\\s.*)?$" );
3910 while ( !in.atEnd() )
3912 line = in.readLine();
3913 const QRegularExpressionMatch match = rx.match( line );
3914 if ( !match.hasMatch() )
3918 const int red = match.captured( 1 ).toInt();
3919 const int green = match.captured( 2 ).toInt();
3920 const int blue = match.captured( 3 ).toInt();
3921 const QColor color = QColor( red, green, blue );
3922 if ( !color.isValid() )
3929 if ( rx.captureCount() > 3 )
3931 label = match.captured( 4 ).simplified();
3938 importedColors << qMakePair( color, label );
3943 return importedColors;
3956 const thread_local QRegularExpression hexColorAlphaRx(
"^\\s*#?([0-9a-fA-F]{6})([0-9a-fA-F]{2})\\s*$" );
3957 QRegularExpressionMatch match = hexColorAlphaRx.match( colorStr );
3960 if ( !match.hasMatch() && QColor::isValidColor( colorStr ) )
3963 parsedColor.setNamedColor( colorStr );
3964 if ( parsedColor.isValid() )
3966 containsAlpha =
false;
3972 if ( match.hasMatch() )
3974 const QString hexColor = match.captured( 1 );
3975 parsedColor.setNamedColor( QStringLiteral(
"#" ) + hexColor );
3977 const int alphaHex = match.captured( 2 ).toInt( &alphaOk, 16 );
3979 if ( parsedColor.isValid() && alphaOk )
3981 parsedColor.setAlpha( alphaHex );
3982 containsAlpha =
true;
3990 const thread_local QRegularExpression hexColorRx2(
"^\\s*(?:[0-9a-fA-F]{3}){1,2}\\s*$" );
3991 if ( colorStr.indexOf( hexColorRx2 ) != -1 )
3994 parsedColor.setNamedColor( QStringLiteral(
"#" ) + colorStr );
3995 if ( parsedColor.isValid() )
3997 containsAlpha =
false;
4004 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*$" );
4005 match = rgbFormatRx.match( colorStr );
4006 if ( match.hasMatch() )
4011 const int r = match.captured( 1 ).toInt( &rOk );
4012 const int g = match.captured( 2 ).toInt( &gOk );
4013 const int b = match.captured( 3 ).toInt( &bOk );
4015 if ( !rOk || !gOk || !bOk )
4017 const float rFloat = match.captured( 1 ).toFloat();
4018 const float gFloat = match.captured( 2 ).toFloat();
4019 const float bFloat = match.captured( 3 ).toFloat();
4020 parsedColor.setRgbF( rFloat / 255.0, gFloat / 255.0, bFloat / 255.0 );
4024 parsedColor.setRgb( r, g, b );
4027 if ( parsedColor.isValid() )
4029 containsAlpha =
false;
4035 const thread_local QRegularExpression hslFormatRx(
"^\\s*hsl\\(?\\s*(\\d+(?:\\.\\d*)?)\\s*,\\s*(\\d+(?:\\.\\d*)?)\\s*%\\s*,\\s*(\\d+(?:\\.\\d*)?)\\s*%\\s*\\)?\\s*;?\\s*$" );
4036 match = hslFormatRx.match( colorStr );
4037 if ( match.hasMatch() )
4042 const int h = match.captured( 1 ).toInt( &hOk );
4043 const int s = match.captured( 2 ).toInt( &sOk );
4044 const int l = match.captured( 3 ).toInt( &lOk );
4046 if ( !hOk || !sOk || !lOk )
4048 const float hFloat = match.captured( 1 ).toFloat();
4049 const float sFloat = match.captured( 2 ).toFloat();
4050 const float lFloat = match.captured( 3 ).toFloat();
4051 parsedColor.setHslF( hFloat / 360.0, sFloat / 100.0, lFloat / 100.0 );
4055 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0 );
4057 if ( parsedColor.isValid() )
4059 containsAlpha =
false;
4065 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*$" );
4066 match = rgbPercentFormatRx.match( colorStr );
4067 if ( match.hasMatch() )
4069 const double r = match.captured( 1 ).toDouble() / 100;
4070 const double g = match.captured( 2 ).toDouble() / 100;
4071 const double b = match.captured( 3 ).toDouble() / 100;
4072 parsedColor.setRgbF( r, g, b );
4073 if ( parsedColor.isValid() )
4075 containsAlpha =
false;
4081 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*$" );
4082 match = rgbaFormatRx.match( colorStr );
4083 if ( match.hasMatch() )
4088 const int r = match.captured( 1 ).toInt( &rOk );
4089 const int g = match.captured( 2 ).toInt( &gOk );
4090 const int b = match.captured( 3 ).toInt( &bOk );
4091 const double aDouble = match.captured( 4 ).toDouble();
4093 if ( !rOk || !gOk || !bOk )
4095 const float rFloat = match.captured( 1 ).toFloat();
4096 const float gFloat = match.captured( 2 ).toFloat();
4097 const float bFloat = match.captured( 3 ).toFloat();
4098 parsedColor.setRgbF( rFloat / 255.0, gFloat / 255.0, bFloat / 255.0, aDouble );
4102 const int a =
static_cast< int >( std::round( match.captured( 4 ).toDouble() * 255.0 ) );
4103 parsedColor.setRgb( r, g, b, a );
4105 if ( parsedColor.isValid() )
4107 containsAlpha =
true;
4113 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*$" );
4114 match = rgbaPercentFormatRx.match( colorStr );
4115 if ( match.hasMatch() )
4117 const double r = match.captured( 1 ).toDouble() / 100;
4118 const double g = match.captured( 2 ).toDouble() / 100;
4119 const double b = match.captured( 3 ).toDouble() / 100;
4120 const double a = match.captured( 4 ).toDouble();
4121 parsedColor.setRgbF( r, g, b, a );
4122 if ( parsedColor.isValid() )
4124 containsAlpha =
true;
4130 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*$" );
4131 match = hslaPercentFormatRx.match( colorStr );
4132 if ( match.hasMatch() )
4137 const int h = match.captured( 1 ).toInt( &hOk );
4138 const int s = match.captured( 2 ).toInt( &sOk );
4139 const int l = match.captured( 3 ).toInt( &lOk );
4140 const double aDouble = match.captured( 4 ).toDouble();
4142 if ( !hOk || !sOk || !lOk )
4144 const float hFloat = match.captured( 1 ).toFloat();
4145 const float sFloat = match.captured( 2 ).toFloat();
4146 const float lFloat = match.captured( 3 ).toFloat();
4147 parsedColor.setHslF( hFloat / 360.0, sFloat / 100.0, lFloat / 100.0, aDouble );
4151 const int a = std::round( aDouble * 255.0 );
4152 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0, a );
4155 if ( parsedColor.isValid() )
4157 containsAlpha =
true;
4174 const QImage::Format format = image->format();
4175 if ( format != QImage::Format_ARGB32_Premultiplied && format != QImage::Format_ARGB32 )
4182 for (
int heightIndex = 0; heightIndex < image->height(); ++heightIndex )
4184 QRgb *scanLine =
reinterpret_cast< QRgb *
>( image->scanLine( heightIndex ) );
4185 for (
int widthIndex = 0; widthIndex < image->width(); ++widthIndex )
4187 myRgb = scanLine[widthIndex];
4188 if ( format == QImage::Format_ARGB32_Premultiplied )
4189 scanLine[widthIndex] = qRgba( opacity * qRed( myRgb ), opacity * qGreen( myRgb ), opacity * qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4191 scanLine[widthIndex] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4199 const int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
4200 const int alpha = ( radius < 1 ) ? 16 : ( radius > 17 ) ? 1 : tab[radius - 1];
4202 if ( image.format() != QImage::Format_ARGB32_Premultiplied
4203 && image.format() != QImage::Format_RGB32 )
4205 image = image.convertToFormat( QImage::Format_ARGB32_Premultiplied );
4208 const int r1 = rect.top();
4209 const int r2 = rect.bottom();
4210 const int c1 = rect.left();
4211 const int c2 = rect.right();
4213 const int bpl = image.bytesPerLine();
4221 i1 = i2 = ( QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3 );
4223 for (
int col = c1; col <= c2; col++ )
4225 p = image.scanLine( r1 ) + col * 4;
4226 for (
int i = i1; i <= i2; i++ )
4227 rgba[i] = p[i] << 4;
4230 for (
int j = r1; j < r2; j++, p += bpl )
4231 for (
int i = i1; i <= i2; i++ )
4232 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4235 for (
int row = r1; row <= r2; row++ )
4237 p = image.scanLine( row ) + c1 * 4;
4238 for (
int i = i1; i <= i2; i++ )
4239 rgba[i] = p[i] << 4;
4242 for (
int j = c1; j < c2; j++, p += 4 )
4243 for (
int i = i1; i <= i2; i++ )
4244 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4247 for (
int col = c1; col <= c2; col++ )
4249 p = image.scanLine( r2 ) + col * 4;
4250 for (
int i = i1; i <= i2; i++ )
4251 rgba[i] = p[i] << 4;
4254 for (
int j = r1; j < r2; j++, p -= bpl )
4255 for (
int i = i1; i <= i2; i++ )
4256 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4259 for (
int row = r1; row <= r2; row++ )
4261 p = image.scanLine( row ) + c2 * 4;
4262 for (
int i = i1; i <= i2; i++ )
4263 rgba[i] = p[i] << 4;
4266 for (
int j = c1; j < c2; j++, p -= 4 )
4267 for (
int i = i1; i <= i2; i++ )
4268 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4274 if ( alpha != 255 && alpha > 0 )
4278 const double alphaFactor = alpha / 255.;
4279 int r = 0, g = 0, b = 0;
4280 rgb.getRgb( &r, &g, &b );
4285 rgb.setRgb( r, g, b, alpha );
4287 else if ( alpha == 0 )
4289 rgb.setRgb( 0, 0, 0, 0 );
4298 if ( !simpleFill || !simpleLine )
4322 if ( simpleLine->
offset() )
4340 if ( order == Qt::AscendingOrder )
4354 const double dx = directionPoint.x() - startPoint.x();
4355 const double dy = directionPoint.y() - startPoint.y();
4356 const double length = std::sqrt( dx * dx + dy * dy );
4357 const double scaleFactor = distance / length;
4358 return QPointF( startPoint.x() + dx * scaleFactor, startPoint.y() + dy * scaleFactor );
4368 for (
int i = 0; i < svgPaths.size(); i++ )
4370 const QDir dir( svgPaths[i] );
4371 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4372 for (
const QString &item : svgSubPaths )
4374 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4377 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4378 for (
const QString &item : svgFiles )
4381 list.append( dir.path() +
'/' + item );
4393 QStringList svgPaths;
4394 svgPaths.append( directory );
4396 for (
int i = 0; i < svgPaths.size(); i++ )
4398 const QDir dir( svgPaths[i] );
4399 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4400 for (
const QString &item : svgSubPaths )
4402 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4405 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4406 for (
const QString &item : svgFiles )
4408 list.append( dir.path() +
'/' + item );
4420 if ( n.startsWith( QLatin1String(
"base64:" ) ) )
4424 if ( QFileInfo::exists( n ) )
4425 return QFileInfo( n ).canonicalFilePath();
4429 if ( name.contains( QLatin1String(
"://" ) ) )
4431 const QUrl url( name );
4432 if ( url.isValid() && !url.scheme().isEmpty() )
4434 if ( url.scheme().compare( QLatin1String(
"file" ), Qt::CaseInsensitive ) == 0 )
4437 name = url.toLocalFile();
4438 if ( QFile( name ).exists() )
4440 return QFileInfo( name ).canonicalFilePath();
4454 for (
int i = 0; i < svgPaths.size(); i++ )
4456 QString svgPath = svgPaths[i];
4457 if ( svgPath.endsWith( QChar(
'/' ) ) )
4468 const QString myLocalPath = svgPath + QDir::separator() + name;
4471 if ( QFile( myLocalPath ).exists() )
4474 return QFileInfo( myLocalPath ).canonicalFilePath();
4478 return pathResolver.
readPath( name );
4486 if ( p.startsWith( QLatin1String(
"base64:" ) ) )
4489 if ( !QFileInfo::exists( p ) )
4492 QString path = QFileInfo( p ).canonicalFilePath();
4496 bool isInSvgPaths =
false;
4497 for (
int i = 0; i < svgPaths.size(); i++ )
4499 const QString dir = QFileInfo( svgPaths[i] ).canonicalFilePath();
4501 if ( !dir.isEmpty() && path.startsWith( dir ) )
4503 path = path.mid( dir.size() + 1 );
4504 isInSvgPaths =
true;
4517 const double *srcX = line->
xData();
4518 const double *srcY = line->
yData();
4520 QPolygonF thisRes( count );
4521 QPointF *dest = thisRes.data();
4522 for (
int i = 0; i < count; ++i )
4524 *dest++ = QPointF( *srcX++, *srcY++ );
4531 if (
const QgsLineString *line = qgsgeometry_cast< const QgsLineString * >( curve ) )
4537 const std::unique_ptr< QgsLineString > straightened( curve->
curveToLine() );
4561 points << QPointF( ( *it ).x(), ( *it ).y() );
4565 points << QPointF( 0, 0 );
4567 return QList< QList<QPolygonF> >() << ( QList< QPolygonF >() << points );
4572 QList< QList<QPolygonF> > res;
4577 res << ( QList< QPolygonF >() <<
curveToPolygonF( qgsgeometry_cast< const QgsCurve * >( *it ) ) );
4585 QList< QList<QPolygonF> > res;
4589 QList<QPolygonF> thisPart;
4590 const QgsCurvePolygon *surface = qgsgeometry_cast< const QgsCurvePolygon * >( *it );
4608 return QList< QList<QPolygonF> >();
4611 return QList< QList<QPolygonF> >();
4618 double cx = 0, cy = 0;
4619 double area, sum = 0;
4620 for (
int i = points.count() - 1, j = 0; j < points.count(); i = j++ )
4622 const QPointF &p1 = points[i];
4623 const QPointF &p2 = points[j];
4624 area = p1.x() * p2.y() - p1.y() * p2.x();
4626 cx += ( p1.x() + p2.x() ) * area;
4627 cy += ( p1.y() + p2.y() ) * area;
4634 if ( points.count() >= 2 )
4635 return QPointF( ( points[0].x() + points[1].x() ) / 2, ( points[0].y() + points[1].y() ) / 2 );
4636 else if ( points.count() == 1 )
4644 return QPointF( cx, cy );
4651 if ( ( rings && rings->count() > 0 ) || !
pointInPolygon( points, centroid ) )
4653 unsigned int i, pointCount = points.count();
4655 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( points[i].x(), points[i].y() );
4661 for (
auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
4663 pointCount = ( *ringIt ).count();
4665 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( ( *ringIt )[i].x(), ( *ringIt )[i].y() );
4671 if ( !pointOnSurfaceGeom.
isNull() )
4674 centroid.
setX( point.
x() );
4675 centroid.
setY( point.
y() );
4680 return QPointF( centroid.
x(), centroid.
y() );
4685 bool inside =
false;
4687 const double x = point.x();
4688 const double y = point.y();
4690 for (
int i = 0, j = points.count() - 1; i < points.count(); i++ )
4692 const QPointF &p1 = points[i];
4693 const QPointF &p2 = points[j];
4698 if ( ( p1.y() < y && p2.y() >= y ) || ( p2.y() < y && p1.y() >= y ) )
4700 if ( p1.x() + ( y - p1.y() ) / ( p2.y() - p1.y() ) * ( p2.x() - p1.x() ) <= x )
4711 if ( polyline.size() < 2 )
4714 double totalLength = 0;
4715 auto it = polyline.begin();
4717 for ( ; it != polyline.end(); ++it )
4719 const QPointF p2 = *it;
4720 const double segmentLength = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4721 totalLength += segmentLength;
4729 if ( polyline.size() < 2 )
4732 double totalLength = 0;
4733 auto it = polyline.begin();
4735 std::vector< double > segmentLengths( polyline.size() - 1 );
4736 auto segmentLengthIt = segmentLengths.begin();
4737 for ( ; it != polyline.end(); ++it )
4739 const QPointF p2 = *it;
4740 *segmentLengthIt = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4741 totalLength += *segmentLengthIt;
4747 if ( startOffset >= 0 && totalLength <= startOffset )
4749 if ( endOffset < 0 && totalLength <= -endOffset )
4752 const double startDistance = startOffset < 0 ? totalLength + startOffset : startOffset;
4753 const double endDistance = endOffset <= 0 ? totalLength + endOffset : endOffset;
4754 QPolygonF substringPoints;
4755 substringPoints.reserve( polyline.size() );
4757 it = polyline.begin();
4758 segmentLengthIt = segmentLengths.begin();
4761 bool foundStart =
false;
4762 if (
qgsDoubleNear( startDistance, 0.0 ) || startDistance < 0 )
4764 substringPoints << p1;
4768 double distanceTraversed = 0;
4769 for ( ; it != polyline.end(); ++it )
4771 const QPointF p2 = *it;
4772 if ( distanceTraversed < startDistance && distanceTraversed + *segmentLengthIt > startDistance )
4775 const double distanceToStart = startDistance - distanceTraversed;
4776 double startX, startY;
4778 substringPoints << QPointF( startX, startY );
4781 if ( foundStart && ( distanceTraversed + *segmentLengthIt > endDistance ) )
4784 const double distanceToEnd = endDistance - distanceTraversed;
4787 if ( substringPoints.last() != QPointF( endX, endY ) )
4788 substringPoints << QPointF( endX, endY );
4790 else if ( foundStart )
4792 if ( substringPoints.last() != QPointF( p2.x(), p2.y() ) )
4793 substringPoints << QPointF( p2.x(), p2.y() );
4796 distanceTraversed += *segmentLengthIt;
4797 if ( distanceTraversed > endDistance )
4804 if ( ( substringPoints.size() < 2 ) || ( substringPoints.size() == 2 && substringPoints.at( 0 ) == substringPoints.at( 1 ) ) )
4807 return substringPoints;
4812 double vertexAngle = M_PI - ( std::atan2( p3.y() - p2.y(), p3.x() - p2.x() ) - std::atan2( p2.y() - p1.y(), p2.x() - p1.x() ) );
4816 return vertexAngle < M_PI * 135.0 / 180.0 || vertexAngle > M_PI * 225.0 / 180.0;
4821 target.reserve( target.size() + line.size() );
4822 for (
const QPointF &pt : line )
4824 if ( !target.empty() && target.last() == pt )
4833 if ( fieldOrExpression.isEmpty() )
4868 QList<double> breaks;
4871 breaks.append( maximum );
4875 const int minimumCount =
static_cast< int >( classes ) / 3;
4876 const double shrink = 0.75;
4877 const double highBias = 1.5;
4878 const double adjustBias = 0.5 + 1.5 * highBias;
4879 const int divisions = classes;
4880 const double h = highBias;
4883 const double dx = maximum - minimum;
4893 cell = std::max( std::fabs( minimum ), std::fabs( maximum ) );
4894 if ( adjustBias >= 1.5 * h + 0.5 )
4896 U = 1 + ( 1.0 / ( 1 + h ) );
4900 U = 1 + ( 1.5 / ( 1 + adjustBias ) );
4902 small = dx < ( cell * U * std::max( 1, divisions ) * 1e-07 * 3.0 );
4909 cell = 9 + cell / 10;
4910 cell = cell * shrink;
4912 if ( minimumCount > 1 )
4914 cell = cell / minimumCount;
4920 if ( divisions > 1 )
4922 cell = cell / divisions;
4925 if ( cell < 20 * 1e-07 )
4930 const double base = std::pow( 10.0, std::floor( std::log10( cell ) ) );
4932 if ( ( 2 * base ) - cell < h * ( cell - unit ) )
4935 if ( ( 5 * base ) - cell < adjustBias * ( cell - unit ) )
4938 if ( ( 10.0 * base ) - cell < h * ( cell - unit ) )
4945 int start = std::floor( minimum / unit + 1e-07 );
4946 int end = std::ceil( maximum / unit - 1e-07 );
4949 while ( start * unit > minimum + ( 1e-07 * unit ) )
4953 while ( end * unit < maximum - ( 1e-07 * unit ) )
4961 int k = std::floor( 0.5 + end - start );
4962 if ( k < minimumCount )
4964 k = minimumCount - k;
4968 start = start - k / 2 + k % 2;
4972 start = start - k / 2;
4973 end = end + k / 2 + k % 2;
4976 const double minimumBreak = start * unit;
4978 const int count = end - start;
4980 breaks.reserve( count );
4981 for (
int i = 1; i < count + 1; i++ )
4983 breaks.append( minimumBreak + i * unit );
4986 if ( breaks.isEmpty() )
4989 if ( breaks.first() < minimum )
4991 breaks[0] = minimum;
4993 if ( breaks.last() > maximum )
4995 breaks[breaks.count() - 1] = maximum;
5000 if ( minimum < 0.0 && maximum > 0.0 )
5002 QList<double> breaksMinusZero;
5003 for (
int i = 0; i < breaks.count(); i++ )
5005 breaksMinusZero.append( breaks[i] - 0.0 );
5008 for (
int i = 1; i < breaks.count(); i++ )
5010 if ( std::abs( breaksMinusZero[i] ) < std::abs( breaksMinusZero[i - 1] ) )
5013 breaks[posOfMin] = 0.0;
5022 bool roundToUnit =
false;
5025 if ( props.contains( QStringLiteral(
"uomScale" ) ) )
5028 scale = props.value( QStringLiteral(
"uomScale" ) ).toDouble( &ok );
5037 if ( props.value( QStringLiteral(
"uom" ) ) == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
5062 scale = 1 / 0.28 * 25.4;
5086 double rescaled = size * scale;
5091 rescaled = std::round( rescaled );
5098 const double x =
rescaleUom( point.x(), unit, props );
5099 const double y =
rescaleUom( point.y(), unit, props );
5100 return QPointF( x, y );
5105 QVector<qreal> result;
5106 QVector<qreal>::const_iterator it = array.constBegin();
5107 for ( ; it != array.constEnd(); ++it )
5109 result.append(
rescaleUom( *it, unit, props ) );
5116 if ( !props.value( QStringLiteral(
"scaleMinDenom" ), QString() ).toString().isEmpty() )
5118 QDomElement scaleMinDenomElem = doc.createElement( QStringLiteral(
"se:MinScaleDenominator" ) );
5119 scaleMinDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMinDenom" ) ).toString().toDouble() ) ) );
5120 ruleElem.appendChild( scaleMinDenomElem );
5123 if ( !props.value( QStringLiteral(
"scaleMaxDenom" ), QString() ).toString().isEmpty() )
5125 QDomElement scaleMaxDenomElem = doc.createElement( QStringLiteral(
"se:MaxScaleDenominator" ) );
5126 scaleMaxDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMaxDenom" ) ).toString().toDouble() ) ) );
5127 ruleElem.appendChild( scaleMaxDenomElem );
5136 const double parentScaleMinDenom = props.value( QStringLiteral(
"scaleMinDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
5137 if ( !ok || parentScaleMinDenom <= 0 )
5138 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( mScaleMinDenom );
5140 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( std::max( parentScaleMinDenom, mScaleMinDenom ) );
5146 const double parentScaleMaxDenom = props.value( QStringLiteral(
"scaleMaxDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
5147 if ( !ok || parentScaleMaxDenom <= 0 )
5148 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( mScaleMaxDenom );
5150 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( std::min( parentScaleMaxDenom, mScaleMaxDenom ) );
5158 if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
5160 scale = 1.0 / 0.00028;
5162 else if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
5164 scale = 304.8 / 0.28;
5171 return size * scale;
5180 SymbolLayerVisitor(
const QSet<QgsSymbolLayerId> &layerIds )
5181 : mSymbolLayerIds( layerIds )
5194 void visitSymbol(
const QgsSymbol *symbol,
const QString &identifier, QVector<int> rootPath )
5198 QVector<int> indexPath = rootPath;
5199 indexPath.append( idx );
5202 if ( mSymbolLayerIds.contains(
QgsSymbolLayerId( mCurrentRuleKey + identifier, indexPath ) ) )
5204 mSymbolLayers.insert( sl );
5210 visitSymbol( subSymbol, identifier, indexPath );
5219 if ( symbolEntity->symbol() )
5221 visitSymbol( symbolEntity->symbol(), leaf.
identifier, {} );
5227 QString mCurrentRuleKey;
5228 const QSet<QgsSymbolLayerId> &mSymbolLayerIds;
5229 QSet<const QgsSymbolLayer *> mSymbolLayers;
5233 SymbolLayerVisitor visitor( symbolLayerIds );
5234 renderer->
accept( &visitor );
5235 return visitor.mSymbolLayers;
5243 SymbolRefreshRateVisitor()
5255 void visitSymbol(
const QgsSymbol *symbol )
5272 if ( refreshRate == -1 || ( animatedMarker->frameRate() > refreshRate ) )
5273 refreshRate = animatedMarker->frameRate();
5277 visitSymbol( subSymbol );
5285 if (
QgsSymbol *symbol = qgis::down_cast<const QgsStyleSymbolEntity *>( leaf.
entity )->symbol() )
5287 visitSymbol( symbol );
5293 double refreshRate = -1;
5296 SymbolRefreshRateVisitor visitor;
5297 renderer->
accept( &visitor );
5298 return visitor.refreshRate;
5303 if ( !s || !context )
5329 size = markerSymbol->
size( *context );
5331 else if ( lineSymbol )
5333 size = lineSymbol->
width( *context );
5345 if ( minSize > 0 && size < minSize )
5349 else if ( maxSize > 0 && size > maxSize )
5368 else if ( lineSymbol )
5383 QMap<QString, QgsProperty>::const_iterator paramIt = propertiesMap.constBegin();
5384 for ( ; paramIt != propertiesMap.constEnd(); ++paramIt )
5386 properties.insert( paramIt.key(), paramIt.value().valueAsString( context ) );
5394 angleRad = std::fmod( angleRad, M_PI * 2 );
5398 angleRad += M_PI * 2;
5402 struct rationalTangent
5414 static const QList<rationalTangent> __rationalTangents
5416 { 1, 57, 0.01754206006 },
5417 { 3, 86, 0.03486958155 },
5418 { 1, 19, 0.05258306161 },
5419 { 3, 43, 0.06965457373 },
5420 { 7, 80, 0.08727771295 },
5421 { 2, 19, 0.1048769387 },
5422 { 7, 57, 0.1221951707 },
5423 { 9, 64, 0.1397088743 },
5424 { 13, 82, 0.157228051 },
5425 { 3, 17, 0.174672199 },
5426 { 7, 36, 0.1920480172 },
5427 { 17, 80, 0.209385393 },
5428 { 3, 13, 0.2267988481 },
5429 { 1, 4, 0.2449786631 },
5430 { 26, 97, 0.2618852647 },
5431 { 27, 94, 0.2797041525 },
5432 { 26, 85, 0.2968446734 },
5433 { 13, 40, 0.3142318991 },
5434 { 21, 61, 0.3315541619 },
5435 { 4, 11, 0.3487710036 },
5436 { 38, 99, 0.3664967859 },
5437 { 40, 99, 0.383984624 },
5438 { 31, 73, 0.4015805401 },
5439 { 41, 92, 0.4192323938 },
5440 { 7, 15, 0.4366271598 },
5441 { 20, 41, 0.4538440015 },
5442 { 27, 53, 0.4711662643 },
5443 { 42, 79, 0.4886424026 },
5444 { 51, 92, 0.5061751436 },
5445 { 56, 97, 0.5235757641 },
5446 { 3, 5, 0.5404195003 },
5447 { 5, 8, 0.5585993153 },
5448 { 50, 77, 0.5759185996 },
5449 { 29, 43, 0.5933501462 },
5450 { 7, 10, 0.6107259644 },
5451 { 69, 95, 0.6281701124 },
5452 { 52, 69, 0.6458159195 },
5453 { 25, 32, 0.6632029927 },
5454 { 17, 21, 0.6805212247 },
5455 { 73, 87, 0.6981204504 },
5456 { 73, 84, 0.7154487784 },
5457 { 9, 10, 0.7328151018 },
5458 { 83, 89, 0.7505285818 },
5459 { 28, 29, 0.7678561033 },
5460 { 1, 1, 0.7853981634 },
5461 { 29, 28, 0.8029402235 },
5462 { 89, 83, 0.820267745 },
5463 { 10, 9, 0.837981225 },
5464 { 107, 93, 0.855284165 },
5465 { 87, 73, 0.8726758763 },
5466 { 121, 98, 0.8900374031 },
5467 { 32, 25, 0.9075933341 },
5468 { 69, 52, 0.9249804073 },
5469 { 128, 93, 0.9424647244 },
5470 { 10, 7, 0.9600703624 },
5471 { 43, 29, 0.9774461806 },
5472 { 77, 50, 0.9948777272 },
5473 { 8, 5, 1.012197011 },
5474 { 163, 98, 1.029475114 },
5475 { 168, 97, 1.047174539 },
5476 { 175, 97, 1.064668696 },
5477 { 126, 67, 1.082075603 },
5478 { 157, 80, 1.099534652 },
5479 { 203, 99, 1.117049384 },
5480 { 193, 90, 1.134452855 },
5481 { 146, 65, 1.151936673 },
5482 { 139, 59, 1.169382787 },
5483 { 99, 40, 1.186811703 },
5484 { 211, 81, 1.204257817 },
5485 { 272, 99, 1.221730164 },
5486 { 273, 94, 1.239188479 },
5487 { 277, 90, 1.25664606 },
5488 { 157, 48, 1.274088705 },
5489 { 279, 80, 1.291550147 },
5490 { 362, 97, 1.308990773 },
5491 { 373, 93, 1.326448578 },
5492 { 420, 97, 1.343823596 },
5493 { 207, 44, 1.361353157 },
5494 { 427, 83, 1.378810994 },
5495 { 414, 73, 1.396261926 },
5496 { 322, 51, 1.413716057 },
5497 { 185, 26, 1.431170275 },
5498 { 790, 97, 1.448623034 },
5499 { 333, 35, 1.466075711 },
5500 { 1063, 93, 1.483530284 },
5501 { 1330, 93, 1.500985147 },
5502 { 706, 37, 1.518436297 },
5503 { 315, 11, 1.535889876 },
5504 { 3953, 69, 1.553343002 },
5510 static const QList<rationalTangent> rationalTangents
5512 { 1, 10, qDegreesToRadians( 5.71059 ) },
5513 { 1, 5, qDegreesToRadians( 11.3099 ) },
5514 { 1, 4, qDegreesToRadians( 14.0362 ) },
5515 { 1, 4, qDegreesToRadians( 18.4349 ) },
5516 { 1, 2, qDegreesToRadians( 26.5651 ) },
5517 { 2, 3, qDegreesToRadians( 33.6901 ) },
5518 { 1, 1, qDegreesToRadians( 45.0 ) },
5519 { 3, 2, qDegreesToRadians( 56.3099 ) },
5520 { 2, 1, qDegreesToRadians( 63.4349 ) },
5521 { 3, 1, qDegreesToRadians( 71.5651 ) },
5522 { 4, 1, qDegreesToRadians( 75.9638 ) },
5523 { 10, 1, qDegreesToRadians( 84.2894 ) },
5526 const int quadrant {
static_cast<int>( angleRad / M_PI_2 ) };
5527 Q_ASSERT( quadrant >= 0 && quadrant <= 3 );
5539 angleRad -= M_PI / 2;
5549 angleRad -= M_PI + M_PI_2;
5571 for (
int idx = 0; idx < rationalTangents.count(); ++idx )
5573 const auto item = rationalTangents.at( idx );
5574 if (
qgsDoubleNear( item.angle, angleRad, 10E-3 ) || item.angle > angleRad )
5581 const rationalTangent bTan { rationalTangents.at( rTanIdx ) };
5582 angleRad = bTan.angle;
5583 const double k { bTan.q *height *width / std::cos( angleRad ) };
5584 const int hcfH { std::gcd( bTan.p * height, bTan.q * width ) };
5585 const int hcfW { std::gcd( bTan.q * height, bTan.p * width ) };
5586 const int W1 {
static_cast<int>( std::round( k / hcfW ) ) };
5587 const int H1 {
static_cast<int>( std::round( k / hcfH ) ) };
5600 angleRad += M_PI / 2;
5613 angleRad += M_PI + M_PI_2;
5624template <
typename Functor>
5627 sl->
setId( generateId() );
5635template <
typename Functor>
5669 maskSl->clearMasks();
5672 if (
QgsSymbol *subSymbol = maskSl->subSymbol() )
5683 if ( clipGeometries.empty() )
5686 if ( bounds.isNull() )
5687 return clipGeometries;
5691 clipGeometries.erase(
5692 std::remove_if( clipGeometries.begin(), clipGeometries.end(), [&boundsRect](
const QgsGeometry & geometry )
5694 return !geometry.boundingBoxIntersects( boundsRect );
5695 } ), clipGeometries.end() );
5697 return clipGeometries;
MarkerClipMode
Marker clipping modes.
@ CompletelyWithin
Render complete markers wherever the completely fall within the polygon shape.
@ NoClipping
No clipping, render complete markers.
@ Shape
Clip to polygon shape.
@ CentroidWithin
Render complete markers wherever their centroid falls within the polygon shape.
LineClipMode
Line clipping modes.
@ NoClipping
Lines are not clipped, will extend to shape's bounding box.
@ ClipPainterOnly
Applying clipping on the painter only (i.e. line endpoints will coincide with polygon bounding box,...
@ ClipToIntersection
Clip lines to intersection with polygon shape (slower) (i.e. line endpoints will coincide with polygo...
ScaleMethod
Scale methods.
@ ScaleDiameter
Calculate scale by the diameter.
@ ScaleArea
Calculate scale by the area.
QFlags< SymbolLayerUserFlag > SymbolLayerUserFlags
Symbol layer user flags.
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
JoinStyle
Join styles for buffers.
@ Bevel
Use beveled joins.
@ Round
Use rounded joins.
@ Miter
Use mitered joins.
RenderUnit
Rendering size units.
@ Percentage
Percentage of another measurement (e.g., canvas size, feature size)
@ Millimeters
Millimeters.
@ Points
Points (e.g., for font sizes)
@ Unknown
Mixed or unknown units.
@ MetersInMapUnits
Meters value as Map units.
EndCapStyle
End cap styles for buffers.
@ Flat
Flat cap (in line with start/end of line)
@ Square
Square cap (extends past start/end of line by buffer distance)
@ RenderSymbolPreview
The render is for a symbol preview only and map based properties may not be available,...
@ Antialiasing
Use antialiasing while drawing.
@ HighQualityImageTransforms
Enable high quality image transformations, which results in better appearance of scaled or rotated ra...
VertexMarkerType
Editing vertex markers, used for showing vertices during a edit operation.
@ SemiTransparentCircle
Semi-transparent circle marker.
QFlags< SymbolRenderHint > SymbolRenderHints
Symbol render hints.
QFlags< SymbolFlag > SymbolFlags
Symbol flags.
@ RendererShouldUseSymbolLevels
If present, indicates that a QgsFeatureRenderer using the symbol should use symbol levels for best re...
@ MultiPolygon
MultiPolygon.
@ MultiLineString
MultiLineString.
SymbolCoordinateReference
Symbol coordinate reference modes.
@ Feature
Relative to feature/shape being rendered.
@ Viewport
Relative to the whole viewport/output device.
Abstract base class for all geometries.
vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry.
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
const_part_iterator const_parts_end() const
Returns STL-style iterator pointing to the imaginary const part after the last part of the geometry.
vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
const_part_iterator const_parts_begin() const
Returns STL-style iterator pointing to the const first part of the geometry.
virtual bool readXml(const QDomElement &collectionElem, const QgsPropertiesDefinition &definitions)
Reads property collection state from an XML element.
virtual bool writeXml(QDomElement &collectionElem, const QgsPropertiesDefinition &definitions) const
Writes the current state of the property collection into an XML element.
Animated marker symbol layer class.
static QgsPaintEffectRegistry * paintEffectRegistry()
Returns the application's paint effect registry, used for managing paint effects.
static QgsSymbolLayerRegistry * symbolLayerRegistry()
Returns the application's symbol layer registry, used for managing symbol layers.
static QStringList svgPaths()
Returns the paths to svg directories.
HeadType
Possible head types.
ArrowType
Possible arrow types.
static QString typeString()
Returns the string identifier for QgsColorBrewerColorRamp.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Returns a new QgsColorBrewerColorRamp color ramp created using the properties encoded in a string map...
Abstract base class for color ramps.
virtual QColor color(double value) const =0
Returns the color corresponding to a specified value.
virtual 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.
QgsGeometry pointOnSurface() const
Returns a point guaranteed to lie on the surface of a geometry.
static QgsGeometry fromPolylineXY(const QgsPolylineXY &polyline)
Creates a new LineString geometry from a list of QgsPointXY points.
QgsPolygonXY asPolygon() const
Returns the contents of the geometry as a polygon.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsPolylineXY asPolyline() const
Returns the contents of the geometry as a polyline.
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
Qgis::GeometryOperationResult addRing(const QVector< QgsPointXY > &ring)
Adds a new ring to this geometry.
QgsMultiPolylineXY asMultiPolyline() const
Returns the contents of the geometry as a multi-linestring.
static QgsGeometry fromPolygonXY(const QgsPolygonXY &polygon)
Creates a new geometry from a QgsPolygonXY.
QgsGeometry buffer(double distance, int segments) const
Returns a buffer region around this geometry having the given width and with a specified number of se...
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsColorRamp from a map of properties.
static QString typeString()
Returns the string identifier for QgsGradientColorRamp.
Represents a patch shape for use in map legends.
static QString typeString()
Returns the string identifier for QgsLimitedRandomColorRamp.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Returns a new QgsLimitedRandomColorRamp color ramp created using the properties encoded in a string m...
Line string geometry type, with support for z-dimension and m-values.
const double * yData() const
Returns a const pointer to the y vertex data.
const double * xData() const
Returns a const pointer to the x vertex data.
int numPoints() const override
Returns the number of points in the curve.
Abstract base class for line symbol layers.
const QgsMapUnitScale & widthMapUnitScale() const
@ AllRings
Render both exterior and interior rings.
RenderRingFilter ringFilter() const
Returns the line symbol layer's ring filter, which controls which rings are rendered when the line sy...
virtual double width() const
Returns the estimated width for the line symbol layer.
double offset() const
Returns the line's offset.
Qgis::RenderUnit widthUnit() const
Returns the units for the line's width.
A line symbol type, for rendering LineString and MultiLineString geometries.
void setWidthUnit(Qgis::RenderUnit unit) const
Sets the width units for the whole symbol (including all symbol layers).
void setWidth(double width) const
Sets the width for the whole line symbol.
double width() const
Returns the estimated width for the whole symbol, which is the maximum width of all marker symbol lay...
Base class for all map layer types.
Struct for storing maximum and minimum scales for measurements in map units.
bool minSizeMMEnabled
Whether the minimum size in mm should be respected.
double maxScale
The maximum scale, or 0.0 if unset.
double minScale
The minimum scale, or 0.0 if unset.
double maxSizeMM
The maximum size in millimeters, or 0.0 if unset.
bool maxSizeMMEnabled
Whether the maximum size in mm should be respected.
double minSizeMM
The minimum size in millimeters, or 0.0 if unset.
A marker symbol type, for rendering Point and MultiPoint geometries.
void setSize(double size) const
Sets the size for the whole symbol.
double size() const
Returns the estimated size for the whole symbol, which is the maximum size of all marker symbol layer...
void setSizeUnit(Qgis::RenderUnit unit) const
Sets the size units for the whole symbol (including all symbol layers).
Special symbol layer that uses its sub symbol as a selective mask.
static QDomElement elseFilterExpression(QDomDocument &doc)
Creates an ElseFilter from doc.
static QDomElement expressionToOgcExpression(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr, bool requiresFilterElement=false)
Creates an OGC expression XML element from the exp expression with default values for the geometry na...
static QDomElement expressionToOgcFilter(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr)
Creates OGC filter XML element.
static QgsExpression * expressionFromOgcFilter(const QDomElement &element, QgsVectorLayer *layer=nullptr)
Parse XML with OGC filter into QGIS expression.
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
virtual bool saveProperties(QDomDocument &doc, QDomElement &element) const
Saves the current state of the effect to a DOM element.
Resolves relative paths into absolute paths and vice versa.
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
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 void clearSymbolLayerMasks(QgsSymbol *symbol)
Remove recursively masks from all symbol symbol layers.
static bool isSharpCorner(QPointF p1, QPointF p2, QPointF p3)
Returns true if the angle formed by the line p1 - p2 - p3 forms a "sharp" corner.
static QString ogrFeatureStylePen(double width, double mmScaleFactor, double mapUnitsScaleFactor, const QColor &c, Qt::PenJoinStyle joinStyle=Qt::MiterJoin, Qt::PenCapStyle capStyle=Qt::FlatCap, double offset=0.0, const QVector< qreal > *dashPattern=nullptr)
Create ogr feature style string for pen.
static Qt::PenCapStyle decodePenCapStyle(const QString &str)
static double rendererFrameRate(const QgsFeatureRenderer *renderer)
Calculates the frame rate (in frames per second) at which the given renderer must be redrawn.
static QgsStringMap getSvgParameterList(QDomElement &element)
static bool needSvgFill(QDomElement &element)
static bool createSymbolLayerListFromSld(QDomElement &element, Qgis::GeometryType geomType, QList< QgsSymbolLayer * > &layers)
Creates a symbol layer list from a DOM element.
static bool externalGraphicFromSld(QDomElement &element, QString &path, QString &mime, QColor &color, double &size)
static 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 Qgis::EndCapStyle penCapStyleToEndCapStyle(Qt::PenCapStyle style)
Converts a Qt pen cap style to a QGIS end cap style.
static QMimeData * symbolToMimeData(const QgsSymbol *symbol)
Creates new mime data from a symbol.
static QString encodeSldFontStyle(QFont::Style style)
static QColor colorFromMimeData(const QMimeData *data, bool &hasAlpha)
Attempts to parse mime data as a color.
static int decodeSldFontWeight(const QString &str)
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
static 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 Qgis::JoinStyle penJoinStyleToJoinStyle(Qt::PenJoinStyle style)
Converts a Qt pen joinstyle to a QGIS join style.
static QIcon symbolPreviewIcon(const QgsSymbol *symbol, QSize size, int padding=0, QgsLegendPatchShape *shape=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Returns an icon preview for a color ramp.
static QMimeData * colorToMimeData(const QColor &color)
Creates mime data from a color.
static bool condenseFillAndOutline(QgsFillSymbolLayer *fill, QgsLineSymbolLayer *outline)
Attempts to condense a fill and outline layer, by moving the outline layer to the fill symbol's strok...
static QPointF decodePoint(const QString &string)
Decodes a QSizeF from a string.
static QPolygonF polylineSubstring(const QPolygonF &polyline, double startOffset, double endOffset)
Returns the substring of a polyline which starts at startOffset from the beginning of the line and en...
static 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.