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" ) )
1299 std::unique_ptr< QgsSymbolLayer > layer =
loadSymbolLayer( e, context );
1303 const QDomElement s = e.firstChildElement( QStringLiteral(
"symbol" ) );
1306 std::unique_ptr< QgsSymbol > subSymbol(
loadSymbol( s, context ) );
1313 layers.append( layer.release() );
1315 for (
int i = 0; i < subSymbol->symbolLayerCount(); ++i )
1317 layers.append( subSymbol->symbolLayer( i )->clone() );
1322 const bool res = layer->setSubSymbol( subSymbol.release() );
1325 QgsDebugError( QStringLiteral(
"symbol layer refused subsymbol: " ) + s.attribute(
"name" ) );
1327 layers.append( layer.release() );
1332 layers.append( layer.release() );
1337 layerNode = layerNode.nextSibling();
1340 if ( layers.isEmpty() )
1346 const QString symbolType = element.attribute( QStringLiteral(
"type" ) );
1348 std::unique_ptr< QgsSymbol > symbol;
1349 if ( symbolType == QLatin1String(
"line" ) )
1350 symbol = std::make_unique< QgsLineSymbol >( layers );
1351 else if ( symbolType == QLatin1String(
"fill" ) )
1352 symbol = std::make_unique< QgsFillSymbol >( layers );
1353 else if ( symbolType == QLatin1String(
"marker" ) )
1354 symbol = std::make_unique< QgsMarkerSymbol >( layers );
1361 if ( element.hasAttribute( QStringLiteral(
"outputUnit" ) ) )
1365 if ( element.hasAttribute( ( QStringLiteral(
"mapUnitScale" ) ) ) )
1368 const double oldMin = element.attribute( QStringLiteral(
"mapUnitMinScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1369 mapUnitScale.
minScale = oldMin != 0 ? 1.0 / oldMin : 0;
1370 const double oldMax = element.attribute( QStringLiteral(
"mapUnitMaxScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1371 mapUnitScale.
maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
1372 symbol->setMapUnitScale( mapUnitScale );
1374 symbol->setOpacity( element.attribute( QStringLiteral(
"alpha" ), QStringLiteral(
"1.0" ) ).toDouble() );
1375 symbol->setExtentBuffer( element.attribute( QStringLiteral(
"extent_buffer" ), QStringLiteral(
"0.0" ) ).toDouble() );
1376 symbol->setExtentBufferSizeUnit(
QgsUnitTypes::decodeRenderUnit( element.attribute( QStringLiteral(
"extent_buffer_unit" ), QStringLiteral(
"MapUnit" ) ) ) );
1377 symbol->setClipFeaturesToExtent( element.attribute( QStringLiteral(
"clip_to_extent" ), QStringLiteral(
"1" ) ).toInt() );
1378 symbol->setForceRHR( element.attribute( QStringLiteral(
"force_rhr" ), QStringLiteral(
"0" ) ).toInt() );
1380 if ( element.attribute( QStringLiteral(
"renderer_should_use_levels" ), QStringLiteral(
"0" ) ).toInt() )
1382 symbol->setFlags( flags );
1384 symbol->animationSettings().setIsAnimated( element.attribute( QStringLiteral(
"is_animated" ), QStringLiteral(
"0" ) ).toInt() );
1385 symbol->animationSettings().setFrameRate( element.attribute( QStringLiteral(
"frame_rate" ), QStringLiteral(
"10" ) ).toDouble() );
1387 if ( !element.firstChildElement( QStringLiteral(
"buffer" ) ).isNull() )
1389 auto bufferSettings = std::make_unique< QgsSymbolBufferSettings >();
1390 bufferSettings->readXml( element, context );
1391 symbol->setBufferSettings( bufferSettings.release() );
1395 symbol->setBufferSettings(
nullptr );
1398 const QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1399 if ( !ddProps.isNull() )
1409 const QString layerClass = element.attribute( QStringLiteral(
"class" ) );
1410 const bool locked = element.attribute( QStringLiteral(
"locked" ) ).toInt();
1411 const bool enabled = element.attribute( QStringLiteral(
"enabled" ), QStringLiteral(
"1" ) ).toInt();
1412 const int pass = element.attribute( QStringLiteral(
"pass" ) ).toInt();
1413 const QString
id = element.attribute( QStringLiteral(
"id" ) );
1427 layer->setLocked( locked );
1428 layer->setRenderingPass( pass );
1429 layer->setEnabled( enabled );
1430 layer->setUserFlags( userFlags );
1433 if ( !
id.isEmpty() )
1437 const QDomElement effectElem = element.firstChildElement( QStringLiteral(
"effect" ) );
1438 if ( !effectElem.isNull() )
1442 layer->setPaintEffect( effect.release() );
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 )
1457 if ( !layer->dataDefinedProperties().propertyKeys().contains( key ) )
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() )
1573 const QString symbolizerName = element.localName();
1575 if ( symbolizerName == QLatin1String(
"PointSymbolizer" ) )
1578 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1579 if ( graphicElem.isNull() )
1581 QgsDebugError( QStringLiteral(
"Graphic element not found in PointSymbolizer" ) );
1592 layers.append( l.release() );
1602 layers.append( l.release() );
1612 layers.append( l.release() );
1624 if ( symbolizerName == QLatin1String(
"LineSymbolizer" ) )
1627 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1628 if ( strokeElem.isNull() )
1630 QgsDebugError( QStringLiteral(
"Stroke element not found in LineSymbolizer" ) );
1643 layers.append( l.release() );
1653 layers.append( l.release() );
1665 if ( symbolizerName == QLatin1String(
"PolygonSymbolizer" ) )
1668 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1669 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1670 if ( fillElem.isNull() && strokeElem.isNull() )
1672 QgsDebugError( QStringLiteral(
"neither Fill nor Stroke element not found in PolygonSymbolizer" ) );
1686 layers.append( l.release() );
1690 if ( lastLayer->
layerType() == QLatin1String(
"SimpleFill" ) || lastLayer->
layerType() == QLatin1String(
"SVGFill" ) )
1698 layers.append( l.release() );
1708 layers.append( l.release() );
1731 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1732 if ( fillElem.isNull() )
1734 QgsDebugError( QStringLiteral(
"Fill element not found" ) );
1738 std::unique_ptr< QgsSymbolLayer > l;
1756 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1757 if ( strokeElem.isNull() )
1759 QgsDebugError( QStringLiteral(
"Stroke element not found" ) );
1763 std::unique_ptr< QgsSymbolLayer > l;
1775 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1776 if ( graphicElem.isNull() )
1778 QgsDebugError( QStringLiteral(
"Graphic element not found" ) );
1782 std::unique_ptr< QgsSymbolLayer > l;
1803 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1804 if ( graphicElem.isNull() )
1807 const QDomElement externalGraphicElem = graphicElem.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
1808 if ( externalGraphicElem.isNull() )
1812 const QDomElement formatElem = externalGraphicElem.firstChildElement( QStringLiteral(
"Format" ) );
1813 if ( formatElem.isNull() )
1816 const QString elementFormat = formatElem.firstChild().nodeValue();
1817 if ( ! format.isEmpty() && elementFormat != format )
1819 QgsDebugMsgLevel(
"unsupported External Graphic format found: " + elementFormat, 4 );
1824 const QDomElement onlineResourceElem = externalGraphicElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1825 const QDomElement inlineContentElem = externalGraphicElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1826 if ( !onlineResourceElem.isNull() )
1831 else if ( !inlineContentElem.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() )
1852 const QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
1853 return !wellKnownNameElem.isNull();
1859 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1860 if ( graphicElem.isNull() )
1863 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1864 if ( markElem.isNull() )
1868 const QDomElement formatElem = markElem.firstChildElement( QStringLiteral(
"Format" ) );
1869 if ( formatElem.isNull() )
1872 const QString format = formatElem.firstChild().nodeValue();
1873 if ( format != QLatin1String(
"ttf" ) )
1875 QgsDebugError(
"unsupported Graphic Mark format found: " + format );
1880 const QDomElement onlineResourceElem = markElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1881 const QDomElement inlineContentElem = markElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1882 if ( !onlineResourceElem.isNull() )
1885 const QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
1886 if ( !markIndexElem.isNull() )
1889 else if ( !inlineContentElem.isNull() )
1904 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1905 if ( graphicElem.isNull() )
1909 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
1911 if ( it.key() == QLatin1String(
"widthHeightFactor" ) )
1922 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1923 if ( strokeElem.isNull() )
1926 QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral(
"GraphicStroke" ) );
1927 if ( graphicStrokeElem.isNull() )
1935 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1936 if ( fillElem.isNull() )
1939 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1940 if ( graphicFillElem.isNull() )
1943 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1944 if ( graphicElem.isNull() )
1950 QColor fillColor, strokeColor;
1951 double size, strokeWidth;
1952 Qt::PenStyle strokeStyle;
1953 if ( !
wellKnownMarkerFromSld( graphicElem, name, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
1956 if ( name != QLatin1String(
"horline" ) )
1964 const double angle = angleFunc.toDouble( &ok );
1970 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1971 if ( fillElem.isNull() )
1974 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1975 if ( graphicFillElem.isNull() )
1978 const QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1979 if ( graphicElem.isNull() )
1982 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1983 if ( markElem.isNull() )
1991 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1992 if ( fillElem.isNull() )
1995 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1996 if ( graphicFillElem.isNull() )
2004 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
2005 if ( fillElem.isNull() )
2008 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
2009 if ( graphicFillElem.isNull() )
2029 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
2030 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
2034 bool validFill =
false, validStroke =
false;
2039 Qt::BrushStyle fillStyle;
2041 if (
fillFromSld( fillElem, fillStyle, fillColor ) )
2047 Qt::PenStyle strokeStyle;
2048 double strokeWidth = 1.0, dashOffset = 0.0;
2049 QVector<qreal> customDashPattern;
2051 if (
lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth,
2052 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2055 if ( validFill || validStroke )
2058 map[QStringLiteral(
"name" )] = QStringLiteral(
"square" );
2061 map[QStringLiteral(
"size" )] = QString::number( 6 );
2062 map[QStringLiteral(
"angle" )] = QString::number( 0 );
2063 map[QStringLiteral(
"offset" )] =
encodePoint( QPointF( 0, 0 ) );
2070 bool validFill =
false, validStroke =
false;
2073 QString name, format;
2075 QColor fillColor, strokeColor;
2076 double strokeWidth = 1.0, size = 0.0, angle = 0.0;
2080 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
2081 if ( !graphicFillElem.isNull() )
2084 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
2085 if ( !graphicElem.isNull() )
2091 const QDomElement graphicChildElem = graphicElem.firstChildElement();
2092 while ( !graphicChildElem.isNull() )
2094 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2097 const QDomElement wellKnownNameElem = graphicChildElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
2098 if ( !wellKnownNameElem.isNull() )
2100 name = wellKnownNameElem.firstChild().nodeValue();
2106 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) || graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2109 const QDomElement formatElem = graphicChildElem.firstChildElement( QStringLiteral(
"Format" ) );
2110 if ( formatElem.isNull() )
2113 format = formatElem.firstChild().nodeValue();
2117 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) && format != QLatin1String(
"image/svg+xml" ) )
2122 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format != QLatin1String(
"ttf" ) )
2126 const QDomElement onlineResourceElem = graphicChildElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
2127 const QDomElement inlineContentElem = graphicChildElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
2129 if ( !onlineResourceElem.isNull() )
2131 name = onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) );
2133 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format == QLatin1String(
"ttf" ) )
2136 if ( name.startsWith( QLatin1String(
"ttf://" ) ) )
2137 name = name.mid( 6 );
2140 const QDomElement markIndexElem = graphicChildElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
2141 if ( markIndexElem.isNull() )
2145 const int v = markIndexElem.firstChild().nodeValue().toInt( &ok );
2156 else if ( !inlineContentElem.isNull() )
2166 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2168 name = QStringLiteral(
"square" );
2175 if ( found && graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2182 Qt::BrushStyle markFillStyle;
2184 QDomElement markFillElem = graphicChildElem.firstChildElement( QStringLiteral(
"Fill" ) );
2185 if (
fillFromSld( markFillElem, markFillStyle, fillColor ) )
2190 Qt::PenStyle strokeStyle;
2191 double strokeWidth = 1.0, dashOffset = 0.0;
2192 QVector<qreal> customDashPattern;
2194 QDomElement markStrokeElem = graphicChildElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2195 if (
lineFromSld( markStrokeElem, strokeStyle, strokeColor, strokeWidth,
2196 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2203 const QDomElement opacityElem = graphicElem.firstChildElement( QStringLiteral(
"Opacity" ) );
2204 if ( !opacityElem.isNull() )
2205 fillColor.setAlpha(
decodeSldAlpha( opacityElem.firstChild().nodeValue() ) );
2207 const QDomElement sizeElem = graphicElem.firstChildElement( QStringLiteral(
"Size" ) );
2208 if ( !sizeElem.isNull() )
2211 const double v = sizeElem.firstChild().nodeValue().toDouble( &ok );
2220 const double v = angleFunc.toDouble( &ok );
2230 if ( validFill || validStroke )
2232 if ( format == QLatin1String(
"image/svg+xml" ) )
2235 map[QStringLiteral(
"name" )] = name;
2236 map[QStringLiteral(
"fill" )] = fillColor.name();
2237 map[QStringLiteral(
"outline" )] = strokeColor.name();
2238 map[QStringLiteral(
"outline-width" )] = QString::number( strokeWidth );
2240 map[QStringLiteral(
"size" )] = QString::number( size );
2242 map[QStringLiteral(
"angle" )] = QString::number( angle );
2243 if ( !offset.isNull() )
2244 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
2247 else if ( format == QLatin1String(
"ttf" ) )
2250 map[QStringLiteral(
"font" )] = name;
2251 map[QStringLiteral(
"chr" )] = markIndex;
2254 map[QStringLiteral(
"size" )] = QString::number( size );
2256 map[QStringLiteral(
"angle" )] = QString::number( angle );
2257 if ( !offset.isNull() )
2258 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
2264 if ( layers.isEmpty() )
2267 layerList << layers;
2274 QString patternName;
2275 switch ( brushStyle )
2280 case Qt::SolidPattern:
2281 if ( color.isValid() )
2284 if ( color.alpha() < 255 )
2289 case Qt::CrossPattern:
2290 case Qt::DiagCrossPattern:
2291 case Qt::HorPattern:
2292 case Qt::VerPattern:
2293 case Qt::BDiagPattern:
2294 case Qt::FDiagPattern:
2295 case Qt::Dense1Pattern:
2296 case Qt::Dense2Pattern:
2297 case Qt::Dense3Pattern:
2298 case Qt::Dense4Pattern:
2299 case Qt::Dense5Pattern:
2300 case Qt::Dense6Pattern:
2301 case Qt::Dense7Pattern:
2306 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( brushStyle ) ) );
2310 QDomElement graphicFillElem = doc.createElement( QStringLiteral(
"se:GraphicFill" ) );
2311 element.appendChild( graphicFillElem );
2313 QDomElement graphicElem = doc.createElement( QStringLiteral(
"se:Graphic" ) );
2314 graphicFillElem.appendChild( graphicElem );
2316 const QColor fillColor = patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
2317 const QColor strokeColor = !patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
2320 wellKnownMarkerToSld( doc, graphicElem, patternName, fillColor, strokeColor, Qt::SolidLine, -1, -1 );
2327 brushStyle = Qt::SolidPattern;
2328 color = QColor( 128, 128, 128 );
2330 if ( element.isNull() )
2332 brushStyle = Qt::NoBrush;
2337 const QDomElement graphicFillElem = element.firstChildElement( QStringLiteral(
"GraphicFill" ) );
2339 if ( graphicFillElem.isNull() )
2342 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2344 QgsDebugMsgLevel( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ), 2 );
2346 if ( it.key() == QLatin1String(
"fill" ) )
2347 color = QColor( it.value() );
2348 else if ( it.key() == QLatin1String(
"fill-opacity" ) )
2354 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
2355 if ( graphicElem.isNull() )
2358 QString patternName = QStringLiteral(
"square" );
2359 QColor fillColor, strokeColor;
2360 double strokeWidth, size;
2361 Qt::PenStyle strokeStyle;
2362 if ( !
wellKnownMarkerFromSld( graphicElem, patternName, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
2366 if ( brushStyle == Qt::NoBrush )
2369 const QColor
c = patternName.startsWith( QLatin1String(
"brush://" ) ) ? fillColor : strokeColor;
2378 Qt::PenStyle penStyle,
const QColor &color,
double width,
2379 const Qt::PenJoinStyle *penJoinStyle,
const Qt::PenCapStyle *penCapStyle,
2380 const QVector<qreal> *customDashPattern,
double dashOffset )
2382 QVector<qreal> dashPattern;
2383 const QVector<qreal> *pattern = &dashPattern;
2385 if ( penStyle == Qt::CustomDashLine && !customDashPattern )
2387 element.appendChild( doc.createComment( QStringLiteral(
"WARNING: Custom dash pattern required but not provided. Using default dash pattern." ) ) );
2388 penStyle = Qt::DashLine;
2400 dashPattern.push_back( 4.0 );
2401 dashPattern.push_back( 2.0 );
2404 dashPattern.push_back( 1.0 );
2405 dashPattern.push_back( 2.0 );
2407 case Qt::DashDotLine:
2408 dashPattern.push_back( 4.0 );
2409 dashPattern.push_back( 2.0 );
2410 dashPattern.push_back( 1.0 );
2411 dashPattern.push_back( 2.0 );
2413 case Qt::DashDotDotLine:
2414 dashPattern.push_back( 4.0 );
2415 dashPattern.push_back( 2.0 );
2416 dashPattern.push_back( 1.0 );
2417 dashPattern.push_back( 2.0 );
2418 dashPattern.push_back( 1.0 );
2419 dashPattern.push_back( 2.0 );
2422 case Qt::CustomDashLine:
2423 Q_ASSERT( customDashPattern );
2424 pattern = customDashPattern;
2428 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( penStyle ) ) );
2432 if ( color.isValid() )
2435 if ( color.alpha() < 255 )
2442 else if ( width == 0 )
2452 if ( !pattern->isEmpty() )
2462 Qt::PenStyle &penStyle, QColor &color,
double &width,
2463 Qt::PenJoinStyle *penJoinStyle, Qt::PenCapStyle *penCapStyle,
2464 QVector<qreal> *customDashPattern,
double *dashOffset )
2468 penStyle = Qt::SolidLine;
2469 color = QColor( 0, 0, 0 );
2472 *penJoinStyle = Qt::BevelJoin;
2474 *penCapStyle = Qt::SquareCap;
2475 if ( customDashPattern )
2476 customDashPattern->clear();
2480 if ( element.isNull() )
2482 penStyle = Qt::NoPen;
2488 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2490 QgsDebugMsgLevel( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ), 2 );
2492 if ( it.key() == QLatin1String(
"stroke" ) )
2494 color = QColor( it.value() );
2496 else if ( it.key() == QLatin1String(
"stroke-opacity" ) )
2500 else if ( it.key() == QLatin1String(
"stroke-width" ) )
2503 const double w = it.value().toDouble( &ok );
2507 else if ( it.key() == QLatin1String(
"stroke-linejoin" ) && penJoinStyle )
2511 else if ( it.key() == QLatin1String(
"stroke-linecap" ) && penCapStyle )
2515 else if ( it.key() == QLatin1String(
"stroke-dasharray" ) )
2518 if ( !dashPattern.isEmpty() )
2522 bool dashPatternFound =
false;
2524 if ( dashPattern.count() == 2 )
2526 if ( dashPattern.at( 0 ) == 4.0 &&
2527 dashPattern.at( 1 ) == 2.0 )
2529 penStyle = Qt::DashLine;
2530 dashPatternFound =
true;
2532 else if ( dashPattern.at( 0 ) == 1.0 &&
2533 dashPattern.at( 1 ) == 2.0 )
2535 penStyle = Qt::DotLine;
2536 dashPatternFound =
true;
2539 else if ( dashPattern.count() == 4 )
2541 if ( dashPattern.at( 0 ) == 4.0 &&
2542 dashPattern.at( 1 ) == 2.0 &&
2543 dashPattern.at( 2 ) == 1.0 &&
2544 dashPattern.at( 3 ) == 2.0 )
2546 penStyle = Qt::DashDotLine;
2547 dashPatternFound =
true;
2550 else if ( dashPattern.count() == 6 )
2552 if ( dashPattern.at( 0 ) == 4.0 &&
2553 dashPattern.at( 1 ) == 2.0 &&
2554 dashPattern.at( 2 ) == 1.0 &&
2555 dashPattern.at( 3 ) == 2.0 &&
2556 dashPattern.at( 4 ) == 1.0 &&
2557 dashPattern.at( 5 ) == 2.0 )
2559 penStyle = Qt::DashDotDotLine;
2560 dashPatternFound =
true;
2565 if ( !dashPatternFound )
2567 if ( customDashPattern )
2569 penStyle = Qt::CustomDashLine;
2570 *customDashPattern = dashPattern;
2574 QgsDebugMsgLevel( QStringLiteral(
"custom dash pattern required but not provided. Using default dash pattern." ), 2 );
2575 penStyle = Qt::DashLine;
2580 else if ( it.key() == QLatin1String(
"stroke-dashoffset" ) && dashOffset )
2583 const double d = it.value().toDouble( &ok );
2593 const QString &path,
const QString &mime,
2594 const QColor &color,
double size )
2596 QDomElement externalGraphicElem = doc.createElement( QStringLiteral(
"se:ExternalGraphic" ) );
2597 element.appendChild( externalGraphicElem );
2606 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2608 element.appendChild( sizeElem );
2613 const QString &path,
const QColor &fillColor,
double size,
const QColor &strokeColor,
double strokeWidth )
2620 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Parametric SVG" ) ) );
2621 const QString parametricPath =
getSvgParametricPath( path, fillColor, strokeColor, strokeWidth );
2624 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Plain SVG fallback, no parameters" ) ) );
2627 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Well known marker fallback" ) ) );
2633 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2635 graphicElem.appendChild( sizeElem );
2643 if ( fillColor.isValid() )
2645 url.addQueryItem( QStringLiteral(
"fill" ), fillColor.name() );
2646 url.addQueryItem( QStringLiteral(
"fill-opacity" ),
encodeSldAlpha( fillColor.alpha() ) );
2650 url.addQueryItem( QStringLiteral(
"fill" ), QStringLiteral(
"#000000" ) );
2651 url.addQueryItem( QStringLiteral(
"fill-opacity" ), QStringLiteral(
"1" ) );
2653 if ( strokeColor.isValid() )
2655 url.addQueryItem( QStringLiteral(
"outline" ), strokeColor.name() );
2656 url.addQueryItem( QStringLiteral(
"outline-opacity" ),
encodeSldAlpha( strokeColor.alpha() ) );
2660 url.addQueryItem( QStringLiteral(
"outline" ), QStringLiteral(
"#000000" ) );
2661 url.addQueryItem( QStringLiteral(
"outline-opacity" ), QStringLiteral(
"1" ) );
2663 url.addQueryItem( QStringLiteral(
"outline-width" ), QString::number( strokeWidth ) );
2664 const QString params = url.toString( QUrl::FullyEncoded );
2665 if ( params.isEmpty() )
2671 return basePath +
"?" + params;
2676 QString &path, QString &mime,
2677 QColor &color,
double &size )
2682 QDomElement externalGraphicElem = element.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
2683 if ( externalGraphicElem.isNull() )
2688 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2689 if ( !sizeElem.isNull() )
2692 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2701 const QString &path,
const QString &format,
int *markIndex,
2702 const QColor &color,
double size )
2704 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2705 element.appendChild( markElem );
2711 QDomElement markIndexElem = doc.createElement( QStringLiteral(
"se:MarkIndex" ) );
2712 markIndexElem.appendChild( doc.createTextNode( QString::number( *markIndex ) ) );
2713 markElem.appendChild( markIndexElem );
2717 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2718 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2719 markElem.appendChild( fillElem );
2724 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2726 element.appendChild( sizeElem );
2731 QString &path, QString &format,
int &markIndex,
2732 QColor &color,
double &size )
2740 QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2741 if ( markElem.isNull() )
2746 const QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
2747 if ( !markIndexElem.isNull() )
2750 const int i = markIndexElem.firstChild().nodeValue().toInt( &ok );
2756 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2757 Qt::BrushStyle b = Qt::SolidPattern;
2762 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2763 if ( !sizeElem.isNull() )
2766 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2775 const QString &name,
const QColor &color,
const QColor &strokeColor, Qt::PenStyle strokeStyle,
2776 double strokeWidth,
double size )
2778 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2779 element.appendChild( markElem );
2781 QDomElement wellKnownNameElem = doc.createElement( QStringLiteral(
"se:WellKnownName" ) );
2782 wellKnownNameElem.appendChild( doc.createTextNode( name ) );
2783 markElem.appendChild( wellKnownNameElem );
2786 if ( color.isValid() )
2788 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2789 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2790 markElem.appendChild( fillElem );
2794 if ( strokeColor.isValid() )
2796 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
2797 lineToSld( doc, strokeElem, strokeStyle, strokeColor, strokeWidth );
2798 markElem.appendChild( strokeElem );
2804 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2806 element.appendChild( sizeElem );
2811 QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle,
2812 double &strokeWidth,
double &size )
2816 name = QStringLiteral(
"square" );
2818 strokeColor = QColor( 0, 0, 0 );
2822 const QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2823 if ( markElem.isNull() )
2826 const QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
2827 if ( !wellKnownNameElem.isNull() )
2829 name = wellKnownNameElem.firstChild().nodeValue();
2834 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2835 Qt::BrushStyle b = Qt::SolidPattern;
2840 QDomElement strokeElem = markElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2841 lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth );
2845 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2846 if ( !sizeElem.isNull() )
2849 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2859 if ( !rotationFunc.isEmpty() )
2861 QDomElement rotationElem = doc.createElement( QStringLiteral(
"se:Rotation" ) );
2863 element.appendChild( rotationElem );
2869 QDomElement rotationElem = element.firstChildElement( QStringLiteral(
"Rotation" ) );
2870 if ( !rotationElem.isNull() )
2880 if ( !alphaFunc.isEmpty() )
2882 QDomElement opacityElem = doc.createElement( QStringLiteral(
"se:Opacity" ) );
2884 element.appendChild( opacityElem );
2890 QDomElement opacityElem = element.firstChildElement( QStringLiteral(
"Opacity" ) );
2891 if ( !opacityElem.isNull() )
2900 if ( offset.isNull() )
2903 QDomElement displacementElem = doc.createElement( QStringLiteral(
"se:Displacement" ) );
2904 element.appendChild( displacementElem );
2906 QDomElement dispXElem = doc.createElement( QStringLiteral(
"se:DisplacementX" ) );
2907 dispXElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.x(), 2 ) ) );
2909 QDomElement dispYElem = doc.createElement( QStringLiteral(
"se:DisplacementY" ) );
2910 dispYElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.y(), 2 ) ) );
2912 displacementElem.appendChild( dispXElem );
2913 displacementElem.appendChild( dispYElem );
2920 QDomElement anchorElem = doc.createElement( QStringLiteral(
"se:AnchorPoint" ) );
2921 element.appendChild( anchorElem );
2923 QDomElement anchorXElem = doc.createElement( QStringLiteral(
"se:AnchorPointX" ) );
2924 anchorXElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.x() ) ) );
2926 QDomElement anchorYElem = doc.createElement( QStringLiteral(
"se:AnchorPointY" ) );
2927 anchorYElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.y() ) ) );
2929 anchorElem.appendChild( anchorXElem );
2930 anchorElem.appendChild( anchorYElem );
2935 offset = QPointF( 0, 0 );
2937 const QDomElement displacementElem = element.firstChildElement( QStringLiteral(
"Displacement" ) );
2938 if ( displacementElem.isNull() )
2941 const QDomElement dispXElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementX" ) );
2942 if ( !dispXElem.isNull() )
2945 const double offsetX = dispXElem.firstChild().nodeValue().toDouble( &ok );
2947 offset.setX( offsetX );
2950 const QDomElement dispYElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementY" ) );
2951 if ( !dispYElem.isNull() )
2954 const double offsetY = dispYElem.firstChild().nodeValue().toDouble( &ok );
2956 offset.setY( offsetY );
2963 const QString &label,
const QFont &font,
2964 const QColor &color,
double size )
2966 QDomElement labelElem = doc.createElement( QStringLiteral(
"se:Label" ) );
2967 labelElem.appendChild( doc.createTextNode( label ) );
2968 element.appendChild( labelElem );
2970 QDomElement fontElem = doc.createElement( QStringLiteral(
"se:Font" ) );
2971 element.appendChild( fontElem );
2975 fontElem.appendChild( createSldParameterElement( doc,
"font-style",
encodeSldFontStyle( font.style() ) ) );
2976 fontElem.appendChild( createSldParameterElement( doc,
"font-weight",
encodeSldFontWeight( font.weight() ) ) );
2981 if ( color.isValid() )
2983 QDomElement fillElem = doc.createElement( QStringLiteral(
"Fill" ) );
2984 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2985 element.appendChild( fillElem );
2990 Qt::PenJoinStyle joinStyle,
2991 Qt::PenCapStyle capStyle,
2993 const QVector<qreal> *dashPattern )
2996 penStyle.append(
"PEN(" );
2997 penStyle.append(
"c:" );
2998 penStyle.append(
c.name() );
2999 penStyle.append(
",w:" );
3001 penStyle.append( QString::number( width * mmScaleFactor ) );
3002 penStyle.append(
"mm" );
3005 if ( dashPattern && !dashPattern->isEmpty() )
3007 penStyle.append(
",p:\"" );
3008 QVector<qreal>::const_iterator pIt = dashPattern->constBegin();
3009 for ( ; pIt != dashPattern->constEnd(); ++pIt )
3011 if ( pIt != dashPattern->constBegin() )
3013 penStyle.append(
' ' );
3015 penStyle.append( QString::number( *pIt * mapUnitScaleFactor ) );
3016 penStyle.append(
'g' );
3018 penStyle.append(
'\"' );
3022 penStyle.append(
",cap:" );
3026 penStyle.append(
'p' );
3029 penStyle.append(
'r' );
3033 penStyle.append(
'b' );
3037 penStyle.append(
",j:" );
3038 switch ( joinStyle )
3041 penStyle.append(
'b' );
3044 penStyle.append(
'r' );
3048 penStyle.append(
'm' );
3054 penStyle.append(
",dp:" );
3055 penStyle.append( QString::number( offset * mapUnitScaleFactor ) );
3056 penStyle.append(
'g' );
3059 penStyle.append(
')' );
3066 brushStyle.append(
"BRUSH(" );
3067 brushStyle.append(
"fc:" );
3068 brushStyle.append( fillColor.name() );
3069 brushStyle.append(
')' );
3075 if ( geomFunc.isEmpty() )
3078 QDomElement geometryElem = doc.createElement( QStringLiteral(
"Geometry" ) );
3079 element.appendChild( geometryElem );
3109 QDomElement geometryElem = element.firstChildElement( QStringLiteral(
"Geometry" ) );
3110 if ( geometryElem.isNull() )
3122 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " + function ) );
3126 if ( !filterElem.isNull() )
3127 element.appendChild( filterElem );
3135 if ( function == QLatin1String(
"ELSE" ) )
3138 element.appendChild( filterElem );
3147 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " + function ) );
3151 if ( !filterElem.isNull() )
3152 element.appendChild( filterElem );
3160 QDomElement elem = element;
3161 if ( element.tagName() != QLatin1String(
"Filter" ) )
3163 const QDomNodeList filterNodes = element.elementsByTagName( QStringLiteral(
"Filter" ) );
3164 if ( !filterNodes.isEmpty() )
3166 elem = filterNodes.at( 0 ).toElement();
3170 if ( elem.isNull() )
3195 const QString &path,
const QString &format )
3199 QDomElement onlineResourceElem = doc.createElement( QStringLiteral(
"se:OnlineResource" ) );
3200 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
3201 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:href" ), url );
3202 element.appendChild( onlineResourceElem );
3204 QDomElement formatElem = doc.createElement( QStringLiteral(
"se:Format" ) );
3205 formatElem.appendChild( doc.createTextNode( format ) );
3206 element.appendChild( formatElem );
3213 const QDomElement onlineResourceElem = element.firstChildElement( QStringLiteral(
"OnlineResource" ) );
3214 if ( onlineResourceElem.isNull() )
3217 path = QUrl::fromPercentEncoding( onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) ).toUtf8() );
3219 const QDomElement formatElem = element.firstChildElement( QStringLiteral(
"Format" ) );
3220 if ( formatElem.isNull() )
3223 format = formatElem.firstChild().nodeValue();
3230 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:SvgParameter" ) );
3231 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
3232 nodeElem.appendChild( doc.createTextNode( value ) );
3241 QDomElement paramElem = element.firstChildElement();
3242 while ( !paramElem.isNull() )
3244 if ( paramElem.localName() == QLatin1String(
"SvgParameter" ) || paramElem.localName() == QLatin1String(
"CssParameter" ) )
3246 const QString name = paramElem.attribute( QStringLiteral(
"name" ) );
3247 if ( paramElem.firstChild().nodeType() == QDomNode::TextNode )
3249 value = paramElem.firstChild().nodeValue();
3253 if ( paramElem.firstChild().nodeType() == QDomNode::ElementNode &&
3254 paramElem.firstChild().localName() == QLatin1String(
"Literal" ) )
3257 value = paramElem.firstChild().firstChild().nodeValue();
3261 QgsDebugError( QStringLiteral(
"unexpected child of %1" ).arg( paramElem.localName() ) );
3265 if ( !name.isEmpty() && !value.isEmpty() )
3266 params[ name ] = value;
3269 paramElem = paramElem.nextSiblingElement();
3277 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:VendorOption" ) );
3278 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
3279 nodeElem.appendChild( doc.createTextNode( value ) );
3287 QDomElement paramElem = element.firstChildElement( QStringLiteral(
"VendorOption" ) );
3288 while ( !paramElem.isNull() )
3290 const QString name = paramElem.attribute( QStringLiteral(
"name" ) );
3291 const QString value = paramElem.firstChild().nodeValue();
3293 if ( !name.isEmpty() && !value.isEmpty() )
3294 params[ name ] = value;
3296 paramElem = paramElem.nextSiblingElement( QStringLiteral(
"VendorOption" ) );
3306 if ( newSymbols.userType() == QMetaType::Type::QVariantMap )
3308 return newSymbols.toMap();
3315 QDomElement e = element.firstChildElement();
3316 while ( !e.isNull() )
3318 if ( e.tagName() == QLatin1String(
"prop" ) )
3320 const QString propKey = e.attribute( QStringLiteral(
"k" ) );
3321 const QString propValue = e.attribute( QStringLiteral(
"v" ) );
3322 props[propKey] = propValue;
3324 e = e.nextSiblingElement();
3341 QDomElement e = element.firstChildElement();
3343 while ( !e.isNull() )
3345 if ( e.tagName() == QLatin1String(
"symbol" ) )
3349 symbols.insert( e.attribute( QStringLiteral(
"name" ) ), symbol.release() );
3355 e = e.nextSiblingElement();
3362 QStringList subsymbols;
3364 for ( QMap<QString, QgsSymbol *>::iterator it = symbols.begin(); it != symbols.end(); ++it )
3366 if ( it.key()[0] !=
'@' )
3370 subsymbols.append( it.key() );
3372 QStringList parts = it.key().split(
'@' );
3373 if ( parts.count() < 3 )
3375 QgsDebugError(
"found subsymbol with invalid name: " + it.key() );
3379 const QString symname = parts[1];
3380 const int symlayer = parts[2].toInt();
3382 if ( !symbols.contains( symname ) )
3384 QgsDebugError(
"subsymbol references invalid symbol: " + symname );
3392 QgsDebugError(
"subsymbol references invalid symbol layer: " + QString::number( symlayer ) );
3401 QgsDebugError(
"symbol layer refused subsymbol: " + it.key() );
3408 for (
int i = 0; i < subsymbols.count(); i++ )
3409 symbols.take( subsymbols[i] );
3416 QDomElement symbolsElem = doc.createElement( tagName );
3419 for ( QMap<QString, QgsSymbol *>::iterator its = symbols.begin(); its != symbols.end(); ++its )
3421 const QDomElement symEl =
saveSymbol( its.key(), its.value(), doc, context );
3422 symbolsElem.appendChild( symEl );
3430 qDeleteAll( symbols );
3439 std::unique_ptr< QMimeData >mimeData(
new QMimeData );
3441 QDomDocument symbolDoc;
3443 symbolDoc.appendChild( symbolElem );
3444 mimeData->setText( symbolDoc.toString() );
3447 mimeData->setColorData( symbol->
color() );
3449 return mimeData.release();
3457 const QString text = data->text();
3458 if ( !text.isEmpty() )
3463 if ( doc.setContent( text ) )
3465 elem = doc.documentElement();
3467 if ( elem.nodeName() != QLatin1String(
"symbol" ) )
3468 elem = elem.firstChildElement( QStringLiteral(
"symbol" ) );
3479 const QString rampType = element.attribute( QStringLiteral(
"type" ) );
3504 QDomElement rampEl = doc.createElement( QStringLiteral(
"colorramp" ) );
3505 rampEl.setAttribute( QStringLiteral(
"type" ), ramp->
type() );
3506 rampEl.setAttribute( QStringLiteral(
"name" ), name );
3514 QVariantMap rampMap;
3516 rampMap.insert( QStringLiteral(
"type" ), ramp->
type() );
3517 rampMap.insert( QStringLiteral(
"name" ), name );
3519 const QVariantMap properties = ramp->
properties();
3521 QVariantMap propertyMap;
3522 for (
auto property = properties.constBegin();
property != properties.constEnd(); ++property )
3524 propertyMap.insert( property.key(),
property.value() );
3527 rampMap.insert( QStringLiteral(
"properties" ), propertyMap );
3533 const QVariantMap rampMap = value.toMap();
3535 const QString rampType = rampMap.value( QStringLiteral(
"type" ) ).toString();
3538 const QVariantMap propertyMap = rampMap.value( QStringLiteral(
"properties" ) ).toMap();
3541 for (
auto property = propertyMap.constBegin();
property != propertyMap.constEnd(); ++property )
3543 props.insert( property.key(),
property.value().toString() );
3565 if ( !color.isValid() )
3572 return color.name();
3577 QList<QColor> colors;
3580 const thread_local QRegularExpression sepCommaSpaceRegExp(
"(,|\\s)" );
3581 QStringList components = colorStr.simplified().split( sepCommaSpaceRegExp );
3582 QStringList::iterator it = components.begin();
3583 for ( ; it != components.end(); ++it )
3585 const QColor result =
parseColor( *it,
true );
3586 if ( result.isValid() )
3591 if ( colors.length() > 0 )
3597 const thread_local QRegularExpression sepCommaRegExp(
"(,|\n)" );
3598 components = colorStr.split( sepCommaRegExp );
3599 it = components.begin();
3600 for ( ; it != components.end(); ++it )
3602 const QColor result =
parseColor( *it,
true );
3603 if ( result.isValid() )
3608 if ( colors.length() > 0 )
3614 components = colorStr.simplified().split( QString(
' ' ) );
3615 it = components.begin();
3616 for ( ; it != components.end(); ++it )
3618 const QColor result =
parseColor( *it,
true );
3619 if ( result.isValid() )
3624 if ( colors.length() > 0 )
3630 components = colorStr.split(
'\n' );
3631 it = components.begin();
3632 for ( ; it != components.end(); ++it )
3634 const QColor result =
parseColor( *it,
true );
3635 if ( result.isValid() )
3648 QMimeData *mimeData =
new QMimeData;
3649 mimeData->setColorData( QVariant( color ) );
3650 mimeData->setText( color.name() );
3657 if ( mimeData->hasColor() )
3659 QColor mimeColor = mimeData->colorData().value<QColor>();
3660 if ( mimeColor.isValid() )
3668 if ( mimeData->hasText() )
3672 if ( textColor.isValid() )
3687 if ( data->hasFormat( QStringLiteral(
"text/xml" ) ) )
3690 const QByteArray encodedData = data->data( QStringLiteral(
"text/xml" ) );
3691 QDomDocument xmlDoc;
3692 xmlDoc.setContent( encodedData );
3694 const QDomElement dragDataElem = xmlDoc.documentElement();
3695 if ( dragDataElem.tagName() == QLatin1String(
"ColorSchemeModelDragData" ) )
3697 const QDomNodeList nodeList = dragDataElem.childNodes();
3698 const int nChildNodes = nodeList.size();
3699 QDomElement currentElem;
3701 for (
int i = 0; i < nChildNodes; ++i )
3703 currentElem = nodeList.at( i ).toElement();
3704 if ( currentElem.isNull() )
3709 QPair< QColor, QString> namedColor;
3711 namedColor.second = currentElem.attribute( QStringLiteral(
"label" ), QString() );
3713 mimeColors << namedColor;
3718 if ( mimeColors.length() == 0 && data->hasFormat( QStringLiteral(
"application/x-colorobject-list" ) ) )
3721 const QByteArray encodedData = data->data( QStringLiteral(
"application/x-colorobject-list" ) );
3722 QDomDocument xmlDoc;
3723 xmlDoc.setContent( encodedData );
3725 const QDomNodeList colorsNodes = xmlDoc.elementsByTagName( QStringLiteral(
"colors" ) );
3726 if ( colorsNodes.length() > 0 )
3728 const QDomElement colorsElem = colorsNodes.at( 0 ).toElement();
3729 const QDomNodeList colorNodeList = colorsElem.childNodes();
3730 const int nChildNodes = colorNodeList.size();
3731 QDomElement currentElem;
3733 for (
int i = 0; i < nChildNodes; ++i )
3736 currentElem = colorNodeList.at( i ).toElement();
3737 if ( currentElem.isNull() )
3742 const QDomNodeList colorNodes = currentElem.elementsByTagName( QStringLiteral(
"color" ) );
3743 const QDomNodeList nameNodes = currentElem.elementsByTagName( QStringLiteral(
"name" ) );
3745 if ( colorNodes.length() > 0 )
3747 const QDomElement colorElem = colorNodes.at( 0 ).toElement();
3749 const QStringList colorParts = colorElem.text().simplified().split(
' ' );
3750 if ( colorParts.length() < 3 )
3755 const int red = colorParts.at( 0 ).toDouble() * 255;
3756 const int green = colorParts.at( 1 ).toDouble() * 255;
3757 const int blue = colorParts.at( 2 ).toDouble() * 255;
3758 QPair< QColor, QString> namedColor;
3759 namedColor.first = QColor( red, green, blue );
3760 if ( nameNodes.length() > 0 )
3762 const QDomElement nameElem = nameNodes.at( 0 ).toElement();
3763 namedColor.second = nameElem.text();
3765 mimeColors << namedColor;
3771 if ( mimeColors.length() == 0 && data->hasText() )
3775 QList< QColor >::iterator it = parsedColors.begin();
3776 for ( ; it != parsedColors.end(); ++it )
3778 mimeColors << qMakePair( *it, QString() );
3782 if ( mimeColors.length() == 0 && data->hasColor() )
3785 const QColor mimeColor = data->colorData().value<QColor>();
3786 if ( mimeColor.isValid() )
3788 mimeColors << qMakePair( mimeColor, QString() );
3798 QMimeData *mimeData =
new QMimeData();
3799 QDomDocument xmlDoc;
3800 QDomElement xmlRootElement = xmlDoc.createElement( QStringLiteral(
"ColorSchemeModelDragData" ) );
3801 xmlDoc.appendChild( xmlRootElement );
3803 QgsNamedColorList::const_iterator colorIt = colorList.constBegin();
3804 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3806 QDomElement namedColor = xmlDoc.createElement( QStringLiteral(
"NamedColor" ) );
3808 namedColor.setAttribute( QStringLiteral(
"label" ), ( *colorIt ).second );
3809 xmlRootElement.appendChild( namedColor );
3811 mimeData->setData( QStringLiteral(
"text/xml" ), xmlDoc.toByteArray() );
3819 colorIt = colorList.constBegin();
3820 QStringList colorListString;
3821 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3823 colorListString << ( *colorIt ).first.name();
3825 mimeData->setText( colorListString.join( QLatin1Char(
'\n' ) ) );
3828 if ( colorList.length() > 0 )
3830 mimeData->setColorData( QVariant( colorList.at( 0 ).first ) );
3838 if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3843 QTextStream stream( &file );
3844#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
3845 stream.setCodec(
"UTF-8" );
3848 stream <<
"GIMP Palette" << Qt::endl;
3849 if ( paletteName.isEmpty() )
3851 stream <<
"Name: QGIS Palette" << Qt::endl;
3855 stream <<
"Name: " << paletteName << Qt::endl;
3857 stream <<
"Columns: 4" << Qt::endl;
3858 stream <<
'#' << Qt::endl;
3860 for ( QgsNamedColorList::ConstIterator colorIt = colors.constBegin(); colorIt != colors.constEnd(); ++colorIt )
3862 const QColor color = ( *colorIt ).first;
3863 if ( !color.isValid() )
3867 stream << QStringLiteral(
"%1 %2 %3" ).arg( color.red(), 3 ).arg( color.green(), 3 ).arg( color.blue(), 3 );
3868 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << Qt::endl;
3879 if ( !file.open( QIODevice::ReadOnly ) )
3882 return importedColors;
3885 QTextStream in( &file );
3886#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
3887 in.setCodec(
"UTF-8" );
3890 QString line = in.readLine();
3891 if ( !line.startsWith( QLatin1String(
"GIMP Palette" ) ) )
3894 return importedColors;
3898 while ( !in.atEnd() && !line.startsWith( QLatin1String(
"Name:" ) ) && !line.startsWith(
'#' ) )
3900 line = in.readLine();
3902 if ( line.startsWith( QLatin1String(
"Name:" ) ) )
3904 const thread_local QRegularExpression nameRx(
"Name:\\s*(\\S.*)$" );
3905 const QRegularExpressionMatch match = nameRx.match( line );
3906 if ( match.hasMatch() )
3908 name = match.captured( 1 );
3913 while ( !in.atEnd() && !line.startsWith(
'#' ) )
3915 line = in.readLine();
3920 return importedColors;
3924 const thread_local QRegularExpression rx(
"^\\s*(\\d+)\\s+(\\d+)\\s+(\\d+)(\\s.*)?$" );
3925 while ( !in.atEnd() )
3927 line = in.readLine();
3928 const QRegularExpressionMatch match = rx.match( line );
3929 if ( !match.hasMatch() )
3933 const int red = match.captured( 1 ).toInt();
3934 const int green = match.captured( 2 ).toInt();
3935 const int blue = match.captured( 3 ).toInt();
3936 const QColor color = QColor( red, green, blue );
3937 if ( !color.isValid() )
3944 if ( rx.captureCount() > 3 )
3946 label = match.captured( 4 ).simplified();
3953 importedColors << qMakePair( color, label );
3958 return importedColors;
3971 const thread_local QRegularExpression hexColorAlphaRx(
"^\\s*#?([0-9a-fA-F]{6})([0-9a-fA-F]{2})\\s*$" );
3972 QRegularExpressionMatch match = hexColorAlphaRx.match( colorStr );
3975 if ( !match.hasMatch() && QColor::isValidColor( colorStr ) )
3978 parsedColor.setNamedColor( colorStr );
3979 if ( parsedColor.isValid() )
3981 containsAlpha =
false;
3987 if ( match.hasMatch() )
3989 const QString hexColor = match.captured( 1 );
3990 parsedColor.setNamedColor( QStringLiteral(
"#" ) + hexColor );
3992 const int alphaHex = match.captured( 2 ).toInt( &alphaOk, 16 );
3994 if ( parsedColor.isValid() && alphaOk )
3996 parsedColor.setAlpha( alphaHex );
3997 containsAlpha =
true;
4005 const thread_local QRegularExpression hexColorRx2(
"^\\s*(?:[0-9a-fA-F]{3}){1,2}\\s*$" );
4006 if ( colorStr.indexOf( hexColorRx2 ) != -1 )
4009 parsedColor.setNamedColor( QStringLiteral(
"#" ) + colorStr );
4010 if ( parsedColor.isValid() )
4012 containsAlpha =
false;
4019 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*$" );
4020 match = rgbFormatRx.match( colorStr );
4021 if ( match.hasMatch() )
4026 const int r = match.captured( 1 ).toInt( &rOk );
4027 const int g = match.captured( 2 ).toInt( &gOk );
4028 const int b = match.captured( 3 ).toInt( &bOk );
4030 if ( !rOk || !gOk || !bOk )
4032 const float rFloat = match.captured( 1 ).toFloat();
4033 const float gFloat = match.captured( 2 ).toFloat();
4034 const float bFloat = match.captured( 3 ).toFloat();
4035 parsedColor.setRgbF( rFloat / 255.0, gFloat / 255.0, bFloat / 255.0 );
4039 parsedColor.setRgb( r, g, b );
4042 if ( parsedColor.isValid() )
4044 containsAlpha =
false;
4050 const thread_local QRegularExpression hslFormatRx(
"^\\s*hsl\\(?\\s*(\\d+(?:\\.\\d*)?)\\s*,\\s*(\\d+(?:\\.\\d*)?)\\s*%\\s*,\\s*(\\d+(?:\\.\\d*)?)\\s*%\\s*\\)?\\s*;?\\s*$" );
4051 match = hslFormatRx.match( colorStr );
4052 if ( match.hasMatch() )
4057 const int h = match.captured( 1 ).toInt( &hOk );
4058 const int s = match.captured( 2 ).toInt( &sOk );
4059 const int l = match.captured( 3 ).toInt( &lOk );
4061 if ( !hOk || !sOk || !lOk )
4063 const float hFloat = match.captured( 1 ).toFloat();
4064 const float sFloat = match.captured( 2 ).toFloat();
4065 const float lFloat = match.captured( 3 ).toFloat();
4066 parsedColor.setHslF( hFloat / 360.0, sFloat / 100.0, lFloat / 100.0 );
4070 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0 );
4072 if ( parsedColor.isValid() )
4074 containsAlpha =
false;
4080 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*$" );
4081 match = rgbPercentFormatRx.match( colorStr );
4082 if ( match.hasMatch() )
4084 const double r = match.captured( 1 ).toDouble() / 100;
4085 const double g = match.captured( 2 ).toDouble() / 100;
4086 const double b = match.captured( 3 ).toDouble() / 100;
4087 parsedColor.setRgbF( r, g, b );
4088 if ( parsedColor.isValid() )
4090 containsAlpha =
false;
4096 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*$" );
4097 match = rgbaFormatRx.match( colorStr );
4098 if ( match.hasMatch() )
4103 const int r = match.captured( 1 ).toInt( &rOk );
4104 const int g = match.captured( 2 ).toInt( &gOk );
4105 const int b = match.captured( 3 ).toInt( &bOk );
4106 const double aDouble = match.captured( 4 ).toDouble();
4108 if ( !rOk || !gOk || !bOk )
4110 const float rFloat = match.captured( 1 ).toFloat();
4111 const float gFloat = match.captured( 2 ).toFloat();
4112 const float bFloat = match.captured( 3 ).toFloat();
4113 parsedColor.setRgbF( rFloat / 255.0, gFloat / 255.0, bFloat / 255.0, aDouble );
4117 const int a =
static_cast< int >( std::round( match.captured( 4 ).toDouble() * 255.0 ) );
4118 parsedColor.setRgb( r, g, b, a );
4120 if ( parsedColor.isValid() )
4122 containsAlpha =
true;
4128 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*$" );
4129 match = rgbaPercentFormatRx.match( colorStr );
4130 if ( match.hasMatch() )
4132 const double r = match.captured( 1 ).toDouble() / 100;
4133 const double g = match.captured( 2 ).toDouble() / 100;
4134 const double b = match.captured( 3 ).toDouble() / 100;
4135 const double a = match.captured( 4 ).toDouble();
4136 parsedColor.setRgbF( r, g, b, a );
4137 if ( parsedColor.isValid() )
4139 containsAlpha =
true;
4145 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*$" );
4146 match = hslaPercentFormatRx.match( colorStr );
4147 if ( match.hasMatch() )
4152 const int h = match.captured( 1 ).toInt( &hOk );
4153 const int s = match.captured( 2 ).toInt( &sOk );
4154 const int l = match.captured( 3 ).toInt( &lOk );
4155 const double aDouble = match.captured( 4 ).toDouble();
4157 if ( !hOk || !sOk || !lOk )
4159 const float hFloat = match.captured( 1 ).toFloat();
4160 const float sFloat = match.captured( 2 ).toFloat();
4161 const float lFloat = match.captured( 3 ).toFloat();
4162 parsedColor.setHslF( hFloat / 360.0, sFloat / 100.0, lFloat / 100.0, aDouble );
4166 const int a = std::round( aDouble * 255.0 );
4167 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0, a );
4170 if ( parsedColor.isValid() )
4172 containsAlpha =
true;
4189 const QImage::Format format = image->format();
4190 if ( format != QImage::Format_ARGB32_Premultiplied && format != QImage::Format_ARGB32 )
4197 for (
int heightIndex = 0; heightIndex < image->height(); ++heightIndex )
4199 QRgb *scanLine =
reinterpret_cast< QRgb *
>( image->scanLine( heightIndex ) );
4200 for (
int widthIndex = 0; widthIndex < image->width(); ++widthIndex )
4202 myRgb = scanLine[widthIndex];
4203 if ( format == QImage::Format_ARGB32_Premultiplied )
4204 scanLine[widthIndex] = qRgba( opacity * qRed( myRgb ), opacity * qGreen( myRgb ), opacity * qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4206 scanLine[widthIndex] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4214 const int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
4215 const int alpha = ( radius < 1 ) ? 16 : ( radius > 17 ) ? 1 : tab[radius - 1];
4217 if ( image.format() != QImage::Format_ARGB32_Premultiplied
4218 && image.format() != QImage::Format_RGB32 )
4220 image = image.convertToFormat( QImage::Format_ARGB32_Premultiplied );
4223 const int r1 = rect.top();
4224 const int r2 = rect.bottom();
4225 const int c1 = rect.left();
4226 const int c2 = rect.right();
4228 const int bpl = image.bytesPerLine();
4236 i1 = i2 = ( QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3 );
4238 for (
int col = c1; col <= c2; col++ )
4240 p = image.scanLine( r1 ) + col * 4;
4241 for (
int i = i1; i <= i2; i++ )
4242 rgba[i] = p[i] << 4;
4245 for (
int j = r1; j < r2; j++, p += bpl )
4246 for (
int i = i1; i <= i2; i++ )
4247 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4250 for (
int row = r1; row <= r2; row++ )
4252 p = image.scanLine( row ) + c1 * 4;
4253 for (
int i = i1; i <= i2; i++ )
4254 rgba[i] = p[i] << 4;
4257 for (
int j = c1; j < c2; j++, p += 4 )
4258 for (
int i = i1; i <= i2; i++ )
4259 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4262 for (
int col = c1; col <= c2; col++ )
4264 p = image.scanLine( r2 ) + col * 4;
4265 for (
int i = i1; i <= i2; i++ )
4266 rgba[i] = p[i] << 4;
4269 for (
int j = r1; j < r2; j++, p -= bpl )
4270 for (
int i = i1; i <= i2; i++ )
4271 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4274 for (
int row = r1; row <= r2; row++ )
4276 p = image.scanLine( row ) + c2 * 4;
4277 for (
int i = i1; i <= i2; i++ )
4278 rgba[i] = p[i] << 4;
4281 for (
int j = c1; j < c2; j++, p -= 4 )
4282 for (
int i = i1; i <= i2; i++ )
4283 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4289 if ( alpha != 255 && alpha > 0 )
4293 const double alphaFactor = alpha / 255.;
4294 int r = 0, g = 0, b = 0;
4295 rgb.getRgb( &r, &g, &b );
4300 rgb.setRgb( r, g, b, alpha );
4302 else if ( alpha == 0 )
4304 rgb.setRgb( 0, 0, 0, 0 );
4313 if ( !simpleFill || !simpleLine )
4337 if ( simpleLine->
offset() )
4355 if ( order == Qt::AscendingOrder )
4369 const double dx = directionPoint.x() - startPoint.x();
4370 const double dy = directionPoint.y() - startPoint.y();
4371 const double length = std::sqrt( dx * dx + dy * dy );
4372 const double scaleFactor = distance / length;
4373 return QPointF( startPoint.x() + dx * scaleFactor, startPoint.y() + dy * scaleFactor );
4383 for (
int i = 0; i < svgPaths.size(); i++ )
4385 const QDir dir( svgPaths[i] );
4386 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4387 for (
const QString &item : svgSubPaths )
4389 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4392 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4393 for (
const QString &item : svgFiles )
4396 list.append( dir.path() +
'/' + item );
4408 QStringList svgPaths;
4409 svgPaths.append( directory );
4411 for (
int i = 0; i < svgPaths.size(); i++ )
4413 const QDir dir( svgPaths[i] );
4414 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4415 for (
const QString &item : svgSubPaths )
4417 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4420 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4421 for (
const QString &item : svgFiles )
4423 list.append( dir.path() +
'/' + item );
4435 if ( n.startsWith( QLatin1String(
"base64:" ) ) )
4439 if ( QFileInfo::exists( n ) )
4440 return QFileInfo( n ).canonicalFilePath();
4444 if ( name.contains( QLatin1String(
"://" ) ) )
4446 const QUrl url( name );
4447 if ( url.isValid() && !url.scheme().isEmpty() )
4449 if ( url.scheme().compare( QLatin1String(
"file" ), Qt::CaseInsensitive ) == 0 )
4452 name = url.toLocalFile();
4453 if ( QFile( name ).exists() )
4455 return QFileInfo( name ).canonicalFilePath();
4469 for (
int i = 0; i < svgPaths.size(); i++ )
4471 QString svgPath = svgPaths[i];
4472 if ( svgPath.endsWith( QChar(
'/' ) ) )
4483 const QString myLocalPath = svgPath + QDir::separator() + name;
4486 if ( QFile( myLocalPath ).exists() )
4489 return QFileInfo( myLocalPath ).canonicalFilePath();
4493 return pathResolver.
readPath( name );
4501 if ( p.startsWith( QLatin1String(
"base64:" ) ) )
4504 if ( !QFileInfo::exists( p ) )
4507 QString path = QFileInfo( p ).canonicalFilePath();
4511 bool isInSvgPaths =
false;
4512 for (
int i = 0; i < svgPaths.size(); i++ )
4514 const QString dir = QFileInfo( svgPaths[i] ).canonicalFilePath();
4516 if ( !dir.isEmpty() && path.startsWith( dir ) )
4518 path = path.mid( dir.size() + 1 );
4519 isInSvgPaths =
true;
4532 const double *srcX = line->
xData();
4533 const double *srcY = line->
yData();
4535 QPolygonF thisRes( count );
4536 QPointF *dest = thisRes.data();
4537 for (
int i = 0; i < count; ++i )
4539 *dest++ = QPointF( *srcX++, *srcY++ );
4546 if (
const QgsLineString *line = qgsgeometry_cast< const QgsLineString * >( curve ) )
4552 const std::unique_ptr< QgsLineString > straightened( curve->
curveToLine() );
4576 points << QPointF( ( *it ).x(), ( *it ).y() );
4580 points << QPointF( 0, 0 );
4582 return QList< QList<QPolygonF> >() << ( QList< QPolygonF >() << points );
4587 QList< QList<QPolygonF> > res;
4592 res << ( QList< QPolygonF >() <<
curveToPolygonF( qgsgeometry_cast< const QgsCurve * >( *it ) ) );
4600 QList< QList<QPolygonF> > res;
4604 QList<QPolygonF> thisPart;
4605 const QgsCurvePolygon *surface = qgsgeometry_cast< const QgsCurvePolygon * >( *it );
4623 return QList< QList<QPolygonF> >();
4626 return QList< QList<QPolygonF> >();
4633 double cx = 0, cy = 0;
4634 double area, sum = 0;
4635 for (
int i = points.count() - 1, j = 0; j < points.count(); i = j++ )
4637 const QPointF &p1 = points[i];
4638 const QPointF &p2 = points[j];
4639 area = p1.x() * p2.y() - p1.y() * p2.x();
4641 cx += ( p1.x() + p2.x() ) * area;
4642 cy += ( p1.y() + p2.y() ) * area;
4649 if ( points.count() >= 2 )
4650 return QPointF( ( points[0].x() + points[1].x() ) / 2, ( points[0].y() + points[1].y() ) / 2 );
4651 else if ( points.count() == 1 )
4659 return QPointF( cx, cy );
4666 if ( ( rings && rings->count() > 0 ) || !
pointInPolygon( points, centroid ) )
4668 unsigned int i, pointCount = points.count();
4670 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( points[i].x(), points[i].y() );
4676 for (
auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
4678 pointCount = ( *ringIt ).count();
4680 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( ( *ringIt )[i].x(), ( *ringIt )[i].y() );
4686 if ( !pointOnSurfaceGeom.
isNull() )
4689 centroid.
setX( point.
x() );
4690 centroid.setY( point.
y() );
4695 return QPointF( centroid.x(), centroid.y() );
4700 bool inside =
false;
4702 const double x = point.x();
4703 const double y = point.y();
4705 for (
int i = 0, j = points.count() - 1; i < points.count(); i++ )
4707 const QPointF &p1 = points[i];
4708 const QPointF &p2 = points[j];
4713 if ( ( p1.y() < y && p2.y() >= y ) || ( p2.y() < y && p1.y() >= y ) )
4715 if ( p1.x() + ( y - p1.y() ) / ( p2.y() - p1.y() ) * ( p2.x() - p1.x() ) <= x )
4726 if ( polyline.size() < 2 )
4729 double totalLength = 0;
4730 auto it = polyline.begin();
4732 for ( ; it != polyline.end(); ++it )
4734 const QPointF p2 = *it;
4735 const double segmentLength = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4736 totalLength += segmentLength;
4744 if ( polyline.size() < 2 )
4747 double totalLength = 0;
4748 auto it = polyline.begin();
4750 std::vector< double > segmentLengths( polyline.size() - 1 );
4751 auto segmentLengthIt = segmentLengths.begin();
4752 for ( ; it != polyline.end(); ++it )
4754 const QPointF p2 = *it;
4755 *segmentLengthIt = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4756 totalLength += *segmentLengthIt;
4762 if ( startOffset >= 0 && totalLength <= startOffset )
4764 if ( endOffset < 0 && totalLength <= -endOffset )
4767 const double startDistance = startOffset < 0 ? totalLength + startOffset : startOffset;
4768 const double endDistance = endOffset <= 0 ? totalLength + endOffset : endOffset;
4769 QPolygonF substringPoints;
4770 substringPoints.reserve( polyline.size() );
4772 it = polyline.begin();
4773 segmentLengthIt = segmentLengths.begin();
4776 bool foundStart =
false;
4777 if (
qgsDoubleNear( startDistance, 0.0 ) || startDistance < 0 )
4779 substringPoints << p1;
4783 double distanceTraversed = 0;
4784 for ( ; it != polyline.end(); ++it )
4786 const QPointF p2 = *it;
4787 if ( distanceTraversed < startDistance && distanceTraversed + *segmentLengthIt > startDistance )
4790 const double distanceToStart = startDistance - distanceTraversed;
4791 double startX, startY;
4793 substringPoints << QPointF( startX, startY );
4796 if ( foundStart && ( distanceTraversed + *segmentLengthIt > endDistance ) )
4799 const double distanceToEnd = endDistance - distanceTraversed;
4802 if ( substringPoints.last() != QPointF( endX, endY ) )
4803 substringPoints << QPointF( endX, endY );
4805 else if ( foundStart )
4807 if ( substringPoints.last() != QPointF( p2.x(), p2.y() ) )
4808 substringPoints << QPointF( p2.x(), p2.y() );
4811 distanceTraversed += *segmentLengthIt;
4812 if ( distanceTraversed > endDistance )
4819 if ( ( substringPoints.size() < 2 ) || ( substringPoints.size() == 2 && substringPoints.at( 0 ) == substringPoints.at( 1 ) ) )
4822 return substringPoints;
4827 double vertexAngle = M_PI - ( std::atan2( p3.y() - p2.y(), p3.x() - p2.x() ) - std::atan2( p2.y() - p1.y(), p2.x() - p1.x() ) );
4831 return vertexAngle < M_PI * 135.0 / 180.0 || vertexAngle > M_PI * 225.0 / 180.0;
4836 target.reserve( target.size() + line.size() );
4837 for (
const QPointF &pt : line )
4839 if ( !target.empty() && target.last() == pt )
4848 if ( fieldOrExpression.isEmpty() )
4851 auto expr = std::make_unique< QgsExpression >( fieldOrExpression );
4852 if ( !expr->hasParserError() )
4857 Q_ASSERT( !expr->hasParserError() );
4882 QList<double> breaks;
4885 breaks.append( maximum );
4889 const int minimumCount =
static_cast< int >( classes ) / 3;
4890 const double shrink = 0.75;
4891 const double highBias = 1.5;
4892 const double adjustBias = 0.5 + 1.5 * highBias;
4893 const int divisions = classes;
4894 const double h = highBias;
4897 const double dx = maximum - minimum;
4907 cell = std::max( std::fabs( minimum ), std::fabs( maximum ) );
4908 if ( adjustBias >= 1.5 * h + 0.5 )
4910 U = 1 + ( 1.0 / ( 1 + h ) );
4914 U = 1 + ( 1.5 / ( 1 + adjustBias ) );
4916 small = dx < ( cell * U * std::max( 1, divisions ) * 1e-07 * 3.0 );
4923 cell = 9 + cell / 10;
4924 cell = cell * shrink;
4926 if ( minimumCount > 1 )
4928 cell = cell / minimumCount;
4934 if ( divisions > 1 )
4936 cell = cell / divisions;
4939 if ( cell < 20 * 1e-07 )
4944 const double base = std::pow( 10.0, std::floor( std::log10( cell ) ) );
4946 if ( ( 2 * base ) - cell < h * ( cell - unit ) )
4949 if ( ( 5 * base ) - cell < adjustBias * ( cell - unit ) )
4952 if ( ( 10.0 * base ) - cell < h * ( cell - unit ) )
4959 int start = std::floor( minimum / unit + 1e-07 );
4960 int end = std::ceil( maximum / unit - 1e-07 );
4963 while ( start * unit > minimum + ( 1e-07 * unit ) )
4967 while ( end * unit < maximum - ( 1e-07 * unit ) )
4975 int k = std::floor( 0.5 + end - start );
4976 if ( k < minimumCount )
4978 k = minimumCount - k;
4982 start = start - k / 2 + k % 2;
4986 start = start - k / 2;
4987 end = end + k / 2 + k % 2;
4990 const double minimumBreak = start * unit;
4992 const int count = end - start;
4994 breaks.reserve( count );
4995 for (
int i = 1; i < count + 1; i++ )
4997 breaks.append( minimumBreak + i * unit );
5000 if ( breaks.isEmpty() )
5003 if ( breaks.first() < minimum )
5005 breaks[0] = minimum;
5007 if ( breaks.last() > maximum )
5009 breaks[breaks.count() - 1] = maximum;
5014 if ( minimum < 0.0 && maximum > 0.0 )
5016 QList<double> breaksMinusZero;
5017 for (
int i = 0; i < breaks.count(); i++ )
5019 breaksMinusZero.append( breaks[i] - 0.0 );
5022 for (
int i = 1; i < breaks.count(); i++ )
5024 if ( std::abs( breaksMinusZero[i] ) < std::abs( breaksMinusZero[i - 1] ) )
5027 breaks[posOfMin] = 0.0;
5036 bool roundToUnit =
false;
5039 if ( props.contains( QStringLiteral(
"uomScale" ) ) )
5042 scale = props.value( QStringLiteral(
"uomScale" ) ).toDouble( &ok );
5051 if ( props.value( QStringLiteral(
"uom" ) ) == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
5076 scale = 1 / 0.28 * 25.4;
5100 double rescaled = size * scale;
5105 rescaled = std::round( rescaled );
5112 const double x =
rescaleUom( point.x(), unit, props );
5113 const double y =
rescaleUom( point.y(), unit, props );
5114 return QPointF( x, y );
5119 QVector<qreal> result;
5120 QVector<qreal>::const_iterator it = array.constBegin();
5121 for ( ; it != array.constEnd(); ++it )
5123 result.append(
rescaleUom( *it, unit, props ) );
5130 if ( !props.value( QStringLiteral(
"scaleMinDenom" ), QString() ).toString().isEmpty() )
5132 QDomElement scaleMinDenomElem = doc.createElement( QStringLiteral(
"se:MinScaleDenominator" ) );
5133 scaleMinDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMinDenom" ) ).toString().toDouble() ) ) );
5134 ruleElem.appendChild( scaleMinDenomElem );
5137 if ( !props.value( QStringLiteral(
"scaleMaxDenom" ), QString() ).toString().isEmpty() )
5139 QDomElement scaleMaxDenomElem = doc.createElement( QStringLiteral(
"se:MaxScaleDenominator" ) );
5140 scaleMaxDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMaxDenom" ) ).toString().toDouble() ) ) );
5141 ruleElem.appendChild( scaleMaxDenomElem );
5150 const double parentScaleMinDenom = props.value( QStringLiteral(
"scaleMinDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
5151 if ( !ok || parentScaleMinDenom <= 0 )
5152 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( mScaleMinDenom );
5154 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( std::max( parentScaleMinDenom, mScaleMinDenom ) );
5160 const double parentScaleMaxDenom = props.value( QStringLiteral(
"scaleMaxDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
5161 if ( !ok || parentScaleMaxDenom <= 0 )
5162 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( mScaleMaxDenom );
5164 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( std::min( parentScaleMaxDenom, mScaleMaxDenom ) );
5172 if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
5174 scale = 1.0 / 0.00028;
5176 else if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
5178 scale = 304.8 / 0.28;
5185 return size * scale;
5194 SymbolLayerVisitor(
const QSet<QgsSymbolLayerId> &layerIds )
5195 : mSymbolLayerIds( layerIds )
5208 void visitSymbol(
const QgsSymbol *symbol,
const QString &identifier, QVector<int> rootPath )
5212 QVector<int> indexPath = rootPath;
5213 indexPath.append( idx );
5216 if ( mSymbolLayerIds.contains(
QgsSymbolLayerId( mCurrentRuleKey + identifier, indexPath ) ) )
5218 mSymbolLayers.insert( sl );
5224 visitSymbol( subSymbol, identifier, indexPath );
5233 if ( symbolEntity->symbol() )
5235 visitSymbol( symbolEntity->symbol(), leaf.
identifier, {} );
5241 QString mCurrentRuleKey;
5242 const QSet<QgsSymbolLayerId> &mSymbolLayerIds;
5243 QSet<const QgsSymbolLayer *> mSymbolLayers;
5247 SymbolLayerVisitor visitor( symbolLayerIds );
5248 renderer->
accept( &visitor );
5249 return visitor.mSymbolLayers;
5257 SymbolRefreshRateVisitor()
5269 void visitSymbol(
const QgsSymbol *symbol )
5286 if ( refreshRate == -1 || ( animatedMarker->frameRate() > refreshRate ) )
5287 refreshRate = animatedMarker->frameRate();
5291 visitSymbol( subSymbol );
5299 if (
QgsSymbol *symbol = qgis::down_cast<const QgsStyleSymbolEntity *>( leaf.
entity )->symbol() )
5301 visitSymbol( symbol );
5307 double refreshRate = -1;
5310 SymbolRefreshRateVisitor visitor;
5311 renderer->
accept( &visitor );
5312 return visitor.refreshRate;
5317 if ( !s || !context )
5343 size = markerSymbol->
size( *context );
5345 else if ( lineSymbol )
5347 size = lineSymbol->
width( *context );
5359 if ( minSize > 0 && size < minSize )
5363 else if ( maxSize > 0 && size > maxSize )
5382 else if ( lineSymbol )
5397 QMap<QString, QgsProperty>::const_iterator paramIt = propertiesMap.constBegin();
5398 for ( ; paramIt != propertiesMap.constEnd(); ++paramIt )
5400 properties.insert( paramIt.key(), paramIt.value().valueAsString( context ) );
5408 angleRad = std::fmod( angleRad, M_PI * 2 );
5412 angleRad += M_PI * 2;
5416 struct rationalTangent
5428 static const QList<rationalTangent> __rationalTangents
5430 { 1, 57, 0.01754206006 },
5431 { 3, 86, 0.03486958155 },
5432 { 1, 19, 0.05258306161 },
5433 { 3, 43, 0.06965457373 },
5434 { 7, 80, 0.08727771295 },
5435 { 2, 19, 0.1048769387 },
5436 { 7, 57, 0.1221951707 },
5437 { 9, 64, 0.1397088743 },
5438 { 13, 82, 0.157228051 },
5439 { 3, 17, 0.174672199 },
5440 { 7, 36, 0.1920480172 },
5441 { 17, 80, 0.209385393 },
5442 { 3, 13, 0.2267988481 },
5443 { 1, 4, 0.2449786631 },
5444 { 26, 97, 0.2618852647 },
5445 { 27, 94, 0.2797041525 },
5446 { 26, 85, 0.2968446734 },
5447 { 13, 40, 0.3142318991 },
5448 { 21, 61, 0.3315541619 },
5449 { 4, 11, 0.3487710036 },
5450 { 38, 99, 0.3664967859 },
5451 { 40, 99, 0.383984624 },
5452 { 31, 73, 0.4015805401 },
5453 { 41, 92, 0.4192323938 },
5454 { 7, 15, 0.4366271598 },
5455 { 20, 41, 0.4538440015 },
5456 { 27, 53, 0.4711662643 },
5457 { 42, 79, 0.4886424026 },
5458 { 51, 92, 0.5061751436 },
5459 { 56, 97, 0.5235757641 },
5460 { 3, 5, 0.5404195003 },
5461 { 5, 8, 0.5585993153 },
5462 { 50, 77, 0.5759185996 },
5463 { 29, 43, 0.5933501462 },
5464 { 7, 10, 0.6107259644 },
5465 { 69, 95, 0.6281701124 },
5466 { 52, 69, 0.6458159195 },
5467 { 25, 32, 0.6632029927 },
5468 { 17, 21, 0.6805212247 },
5469 { 73, 87, 0.6981204504 },
5470 { 73, 84, 0.7154487784 },
5471 { 9, 10, 0.7328151018 },
5472 { 83, 89, 0.7505285818 },
5473 { 28, 29, 0.7678561033 },
5474 { 1, 1, 0.7853981634 },
5475 { 29, 28, 0.8029402235 },
5476 { 89, 83, 0.820267745 },
5477 { 10, 9, 0.837981225 },
5478 { 107, 93, 0.855284165 },
5479 { 87, 73, 0.8726758763 },
5480 { 121, 98, 0.8900374031 },
5481 { 32, 25, 0.9075933341 },
5482 { 69, 52, 0.9249804073 },
5483 { 128, 93, 0.9424647244 },
5484 { 10, 7, 0.9600703624 },
5485 { 43, 29, 0.9774461806 },
5486 { 77, 50, 0.9948777272 },
5487 { 8, 5, 1.012197011 },
5488 { 163, 98, 1.029475114 },
5489 { 168, 97, 1.047174539 },
5490 { 175, 97, 1.064668696 },
5491 { 126, 67, 1.082075603 },
5492 { 157, 80, 1.099534652 },
5493 { 203, 99, 1.117049384 },
5494 { 193, 90, 1.134452855 },
5495 { 146, 65, 1.151936673 },
5496 { 139, 59, 1.169382787 },
5497 { 99, 40, 1.186811703 },
5498 { 211, 81, 1.204257817 },
5499 { 272, 99, 1.221730164 },
5500 { 273, 94, 1.239188479 },
5501 { 277, 90, 1.25664606 },
5502 { 157, 48, 1.274088705 },
5503 { 279, 80, 1.291550147 },
5504 { 362, 97, 1.308990773 },
5505 { 373, 93, 1.326448578 },
5506 { 420, 97, 1.343823596 },
5507 { 207, 44, 1.361353157 },
5508 { 427, 83, 1.378810994 },
5509 { 414, 73, 1.396261926 },
5510 { 322, 51, 1.413716057 },
5511 { 185, 26, 1.431170275 },
5512 { 790, 97, 1.448623034 },
5513 { 333, 35, 1.466075711 },
5514 { 1063, 93, 1.483530284 },
5515 { 1330, 93, 1.500985147 },
5516 { 706, 37, 1.518436297 },
5517 { 315, 11, 1.535889876 },
5518 { 3953, 69, 1.553343002 },
5524 static const QList<rationalTangent> rationalTangents
5526 { 1, 10, qDegreesToRadians( 5.71059 ) },
5527 { 1, 5, qDegreesToRadians( 11.3099 ) },
5528 { 1, 4, qDegreesToRadians( 14.0362 ) },
5529 { 1, 4, qDegreesToRadians( 18.4349 ) },
5530 { 1, 2, qDegreesToRadians( 26.5651 ) },
5531 { 2, 3, qDegreesToRadians( 33.6901 ) },
5532 { 1, 1, qDegreesToRadians( 45.0 ) },
5533 { 3, 2, qDegreesToRadians( 56.3099 ) },
5534 { 2, 1, qDegreesToRadians( 63.4349 ) },
5535 { 3, 1, qDegreesToRadians( 71.5651 ) },
5536 { 4, 1, qDegreesToRadians( 75.9638 ) },
5537 { 10, 1, qDegreesToRadians( 84.2894 ) },
5540 const int quadrant {
static_cast<int>( angleRad / M_PI_2 ) };
5541 Q_ASSERT( quadrant >= 0 && quadrant <= 3 );
5553 angleRad -= M_PI / 2;
5563 angleRad -= M_PI + M_PI_2;
5585 for (
int idx = 0; idx < rationalTangents.count(); ++idx )
5587 const auto item = rationalTangents.at( idx );
5588 if (
qgsDoubleNear( item.angle, angleRad, 10E-3 ) || item.angle > angleRad )
5595 const rationalTangent bTan { rationalTangents.at( rTanIdx ) };
5596 angleRad = bTan.angle;
5597 const double k { bTan.q *height *width / std::cos( angleRad ) };
5598 const int hcfH { std::gcd( bTan.p * height, bTan.q * width ) };
5599 const int hcfW { std::gcd( bTan.q * height, bTan.p * width ) };
5600 const int W1 {
static_cast<int>( std::round( k / hcfW ) ) };
5601 const int H1 {
static_cast<int>( std::round( k / hcfH ) ) };
5614 angleRad += M_PI / 2;
5627 angleRad += M_PI + M_PI_2;
5638template <
typename Functor>
5641 sl->
setId( generateId() );
5649template <
typename Functor>
5683 maskSl->clearMasks();
5686 if (
QgsSymbol *subSymbol = maskSl->subSymbol() )
5697 if ( clipGeometries.empty() )
5700 if ( bounds.isNull() )
5701 return clipGeometries;
5705 clipGeometries.erase(
5706 std::remove_if( clipGeometries.begin(), clipGeometries.end(), [&boundsRect](
const QgsGeometry & geometry )
5708 return !geometry.boundingBoxIntersects( boundsRect );
5709 } ), clipGeometries.end() );
5711 return clipGeometries;
MarkerClipMode
Marker clipping modes.
@ CompletelyWithin
Render complete markers wherever the completely fall within the polygon shape.
@ NoClipping
No clipping, render complete markers.
@ Shape
Clip to polygon shape.
@ CentroidWithin
Render complete markers wherever their centroid falls within the polygon shape.
LineClipMode
Line clipping modes.
@ NoClipping
Lines are not clipped, will extend to shape's bounding box.
@ ClipPainterOnly
Applying clipping on the painter only (i.e. line endpoints will coincide with polygon bounding box,...
@ ClipToIntersection
Clip lines to intersection with polygon shape (slower) (i.e. line endpoints will coincide with polygo...
ScaleMethod
Scale methods.
@ ScaleDiameter
Calculate scale by the diameter.
@ ScaleArea
Calculate scale by the area.
QFlags< SymbolLayerUserFlag > SymbolLayerUserFlags
Symbol layer user flags.
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
JoinStyle
Join styles for buffers.
@ Bevel
Use beveled joins.
@ Round
Use rounded joins.
@ Miter
Use mitered joins.
RenderUnit
Rendering size units.
@ Percentage
Percentage of another measurement (e.g., canvas size, feature size)
@ Millimeters
Millimeters.
@ Points
Points (e.g., for font sizes)
@ Unknown
Mixed or unknown units.
@ MetersInMapUnits
Meters value as Map units.
EndCapStyle
End cap styles for buffers.
@ Flat
Flat cap (in line with start/end of line)
@ Square
Square cap (extends past start/end of line by buffer distance)
@ RenderSymbolPreview
The render is for a symbol preview only and map based properties may not be available,...
@ Antialiasing
Use antialiasing while drawing.
@ HighQualityImageTransforms
Enable high quality image transformations, which results in better appearance of scaled or rotated ra...
VertexMarkerType
Editing vertex markers, used for showing vertices during a edit operation.
@ SemiTransparentCircle
Semi-transparent circle marker.
QFlags< SymbolRenderHint > SymbolRenderHints
Symbol render hints.
QFlags< SymbolFlag > SymbolFlags
Symbol flags.
@ RendererShouldUseSymbolLevels
If present, indicates that a QgsFeatureRenderer using the symbol should use symbol levels for best re...
@ MultiPolygon
MultiPolygon.
@ MultiLineString
MultiLineString.
SymbolCoordinateReference
Symbol coordinate reference modes.
@ Feature
Relative to feature/shape being rendered.
@ Viewport
Relative to the whole viewport/output device.
Abstract base class for all geometries.
vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry.
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
const_part_iterator const_parts_end() const
Returns STL-style iterator pointing to the imaginary const part after the last part of the geometry.
vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
const_part_iterator const_parts_begin() const
Returns STL-style iterator pointing to the const first part of the geometry.
virtual bool readXml(const QDomElement &collectionElem, const QgsPropertiesDefinition &definitions)
Reads property collection state from an XML element.
virtual bool writeXml(QDomElement &collectionElem, const QgsPropertiesDefinition &definitions) const
Writes the current state of the property collection into an XML element.
Animated marker symbol layer class.
static QgsPaintEffectRegistry * paintEffectRegistry()
Returns the application's paint effect registry, used for managing paint effects.
static QgsSymbolLayerRegistry * symbolLayerRegistry()
Returns the application's symbol layer registry, used for managing symbol layers.
static QStringList svgPaths()
Returns the paths to svg directories.
HeadType
Possible head types.
ArrowType
Possible arrow types.
static QString typeString()
Returns the string identifier for QgsColorBrewerColorRamp.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Returns a new QgsColorBrewerColorRamp color ramp created using the properties encoded in a string map...
Abstract base class for color ramps.
virtual QColor color(double value) const =0
Returns the color corresponding to a specified value.
virtual QVariantMap properties() const =0
Returns a string map containing all the color ramp's properties.
virtual QString type() const =0
Returns a string representing the color ramp type.
static QColor colorFromString(const QString &string)
Decodes a string into a color value.
static QString colorToString(const QColor &color)
Encodes a color into a string value.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates the symbol layer.
static QString typeString()
Returns the string identifier for QgsCptCityColorRamp.
Curve polygon geometry type.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
Abstract base class for curved geometry type.
virtual QgsLineString * curveToLine(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const =0
Returns a new line string geometry corresponding to a segmentized approximation of the curve.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
bool hasFeature() const
Returns true if the context has a feature associated with it.
An expression node which takes its value from a feature's field.
Abstract base class for all nodes that can appear in an expression.
virtual QgsExpressionNode::NodeType nodeType() const =0
Gets the type of this node.
Handles parsing and evaluation of expressions (formerly called "search strings").
QString expression() const
Returns the original, unmodified expression string.
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
QString parserErrorString() const
Returns parser error.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
const QgsExpressionNode * rootNode() const
Returns the root node of the expression.
Abstract base class for all 2D vector feature renderers.
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
Abstract base class for fill symbol layers.
static void pointOnLineWithDistance(double x1, double y1, double x2, double y2, double distance, double &x, double &y, double *z1=nullptr, double *z2=nullptr, double *z=nullptr, double *m1=nullptr, double *m2=nullptr, double *m=nullptr)
Calculates the point a specified distance from (x1, y1) toward a second point (x2,...
static double normalizedAngle(double angle)
Ensures that an angle is in the range 0 <= angle < 2 pi.
A geometry is the spatial representation of a feature.
QgsMultiPolygonXY asMultiPolygon() const
Returns the contents of the geometry as a multi-polygon.
QgsGeometry offsetCurve(double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit) const
Returns an offset line at a given distance and side from an input line.
QgsGeometry pointOnSurface() const
Returns a point guaranteed to lie on the surface of a geometry.
static QgsGeometry fromPolylineXY(const QgsPolylineXY &polyline)
Creates a new LineString geometry from a list of QgsPointXY points.
QgsPolygonXY asPolygon() const
Returns the contents of the geometry as a polygon.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsPolylineXY asPolyline() const
Returns the contents of the geometry as a polyline.
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
Qgis::GeometryOperationResult addRing(const QVector< QgsPointXY > &ring)
Adds a new ring to this geometry.
QgsMultiPolylineXY asMultiPolyline() const
Returns the contents of the geometry as a multi-linestring.
static QgsGeometry fromPolygonXY(const QgsPolygonXY &polygon)
Creates a new geometry from a QgsPolygonXY.
QgsGeometry buffer(double distance, int segments) const
Returns a buffer region around this geometry having the given width and with a specified number of se...
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsColorRamp from a map of properties.
static QString typeString()
Returns the string identifier for QgsGradientColorRamp.
Represents a patch shape for use in map legends.
static QString typeString()
Returns the string identifier for QgsLimitedRandomColorRamp.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Returns a new QgsLimitedRandomColorRamp color ramp created using the properties encoded in a string m...
Line string geometry type, with support for z-dimension and m-values.
const double * yData() const
Returns a const pointer to the y vertex data.
const double * xData() const
Returns a const pointer to the x vertex data.
int numPoints() const override
Returns the number of points in the curve.
Abstract base class for line symbol layers.
const QgsMapUnitScale & widthMapUnitScale() const
@ AllRings
Render both exterior and interior rings.
RenderRingFilter ringFilter() const
Returns the line symbol layer's ring filter, which controls which rings are rendered when the line sy...
virtual double width() const
Returns the estimated width for the line symbol layer.
double offset() const
Returns the line's offset.
Qgis::RenderUnit widthUnit() const
Returns the units for the line's width.
A line symbol type, for rendering LineString and MultiLineString geometries.
void setWidthUnit(Qgis::RenderUnit unit) const
Sets the width units for the whole symbol (including all symbol layers).
void setWidth(double width) const
Sets the width for the whole line symbol.
double width() const
Returns the estimated width for the whole symbol, which is the maximum width of all marker symbol lay...
Base class for all map layer types.
Struct for storing maximum and minimum scales for measurements in map units.
bool minSizeMMEnabled
Whether the minimum size in mm should be respected.
double maxScale
The maximum scale, or 0.0 if unset.
double minScale
The minimum scale, or 0.0 if unset.
double maxSizeMM
The maximum size in millimeters, or 0.0 if unset.
bool maxSizeMMEnabled
Whether the maximum size in mm should be respected.
double minSizeMM
The minimum size in millimeters, or 0.0 if unset.
A marker symbol type, for rendering Point and MultiPoint geometries.
void setSize(double size) const
Sets the size for the whole symbol.
double size() const
Returns the estimated size for the whole symbol, which is the maximum size of all marker symbol layer...
void setSizeUnit(Qgis::RenderUnit unit) const
Sets the size units for the whole symbol (including all symbol layers).
Special symbol layer that uses its sub symbol as a selective mask.
static QDomElement elseFilterExpression(QDomDocument &doc)
Creates an ElseFilter from doc.
static QDomElement expressionToOgcExpression(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr, bool requiresFilterElement=false)
Creates an OGC expression XML element from the exp expression with default values for the geometry na...
static QDomElement expressionToOgcFilter(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr)
Creates OGC filter XML element.
static QgsExpression * expressionFromOgcFilter(const QDomElement &element, QgsVectorLayer *layer=nullptr)
Parse XML with OGC filter into QGIS expression.
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
virtual bool saveProperties(QDomDocument &doc, QDomElement &element) const
Saves the current state of the effect to a DOM element.
Resolves relative paths into absolute paths and vice versa.
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
void setX(double x)
Sets the x value of the point.
static QString typeString()
Returns the string identifier for QgsPresetSchemeColorRamp.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Returns a new QgsPresetSchemeColorRamp color ramp created using the properties encoded in a string ma...
A grouped map of multiple QgsProperty objects, each referenced by an integer key value.
QSet< int > propertyKeys() const final
Returns a list of property keys contained within the collection.
QgsProperty property(int key) const final
Returns a matching property from the collection, if one exists.
A store for object properties.
bool isProjectColor() const
Returns true if the property is set to a linked project color.
bool isActive() const
Returns whether the property is currently active.
void setActive(bool active)
Sets whether the property is currently active.
A container for the context for various read/write operations on objects.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
A rectangle specified with double values.
Contains information about the context of a rendering operation.
void setForceVectorOutput(bool force)
Sets whether rendering operations should use vector operations instead of any faster raster shortcuts...
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
void setDevicePixelRatio(float ratio)
Sets the device pixel ratio.
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
QgsExpressionContext & expressionContext()
Gets the expression context.
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
QVector< QgsGeometry > symbolLayerClipGeometries(const QString &symbolLayerId) const
Returns clipping geometries to be applied to the symbolLayer before rendering.
static QgsRenderContext fromQPainter(QPainter *painter)
Creates a default render context given a pixel based QPainter destination.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
A fill symbol layer which fills polygons with a repeated SVG file.
Stores properties relating to a screen.
double devicePixelRatio() const
Returns the ratio between physical pixels and device-independent pixels for the screen.
bool isValid() const
Returns true if the properties are valid.
void updateRenderContextForScreen(QgsRenderContext &context) const
Updates the settings in a render context to match the screen settings.
Renders polygons using a single fill and stroke color.
void setStrokeWidthMapUnitScale(const QgsMapUnitScale &scale)
void setStrokeWidthUnit(Qgis::RenderUnit unit)
Sets the units for the width of the fill's stroke.
void setPenJoinStyle(Qt::PenJoinStyle style)
void setStrokeWidth(double strokeWidth)
void setStrokeStyle(Qt::PenStyle strokeStyle)
void setStrokeColor(const QColor &strokeColor) override
Sets the stroke color for the symbol layer.
A simple line symbol layer, which renders lines using a line in a variety of styles (e....
bool tweakDashPatternOnCorners() const
Returns true if dash patterns tweaks should be applied on sharp corners, to ensure that a double-leng...
Qt::PenJoinStyle penJoinStyle() const
Returns the pen join style used to render the line (e.g.
double trimDistanceStart() const
Returns the trim distance for the start of the line, which dictates a length from the start of the li...
double trimDistanceEnd() const
Returns the trim distance for the end of the line, which dictates a length from the end of the line a...
bool useCustomDashPattern() const
Returns true if the line uses a custom dash pattern.
Qt::PenStyle penStyle() const
Returns the pen style used to render the line (e.g.
double dashPatternOffset() const
Returns the dash pattern offset, which dictates how far along the dash pattern the pattern should sta...
bool drawInsidePolygon() const
Returns true if the line should only be drawn inside polygons, and any portion of the line which fall...
bool alignDashPattern() const
Returns true if dash patterns should be aligned to the start and end of lines, by applying subtle twe...
virtual QgsStyle::StyleEntity type() const =0
Returns the type of style entity.
An interface for classes which can visit style entity (e.g.
@ SymbolRule
Rule based symbology or label child rule.
A symbol entity for QgsStyle databases.
bool isAnimated() const
Returns true if the symbol is animated.
double frameRate() const
Returns the symbol animation frame rate (in frames per second).
Contains settings relating to symbol buffers, which draw a "halo" effect around the symbol.
We may need stable references to symbol layers, when pointers to symbol layers are not usable (when a...
std::unique_ptr< QgsSymbolLayer > createSymbolLayerFromSld(const QString &name, QDomElement &element) const
create a new instance of symbol layer given symbol layer name and SLD
void resolvePaths(const QString &name, QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving) const
Resolve paths in properties of a particular symbol layer.
void resolveFonts(const QString &name, QVariantMap &properties, const QgsReadWriteContext &context) const
Resolve fonts from the properties of a particular symbol layer.
std::unique_ptr< QgsSymbolLayer > createSymbolLayer(const QString &name, const QVariantMap &properties=QVariantMap()) const
create a new instance of symbol layer given symbol layer name and properties
static bool externalMarkerFromSld(QDomElement &element, QString &path, QString &format, int &markIndex, QColor &color, double &size)
static QColor parseColor(const QString &colorStr, bool strictEval=false)
Attempts to parse a string as a color using a variety of common formats, including hex codes,...
static bool rotationFromSldElement(QDomElement &element, QString &rotationFunc)
static void createAnchorPointElement(QDomDocument &doc, QDomElement &element, QPointF anchor)
Creates a SE 1.1 anchor point element as a child of the specified element.
static void sortVariantList(QList< QVariant > &list, Qt::SortOrder order)
Sorts the passed list in requested order.
static Qgis::MarkerClipMode decodeMarkerClipMode(const QString &string, bool *ok=nullptr)
Decodes a string representing a marker clip mode.
static QPicture symbolLayerPreviewPicture(const QgsSymbolLayer *layer, Qgis::RenderUnit units, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::SymbolType parentSymbolType=Qgis::SymbolType::Hybrid)
Draws a symbol layer preview to a QPicture.
static bool hasExternalGraphic(QDomElement &element)
Checks if element contains an ExternalGraphic element with format "image/svg+xml".
static QString encodePenStyle(Qt::PenStyle style)
static bool needMarkerLine(QDomElement &element)
static QVector< qreal > decodeSldRealVector(const QString &s)
static bool needLinePatternFill(QDomElement &element)
static std::unique_ptr< QgsSymbol > symbolFromMimeData(const QMimeData *data)
Attempts to parse mime data as a symbol.
static void clearSymbolLayerIds(QgsSymbol *symbol)
Remove recursively unique id from all symbol symbol layers and set an empty string instead.
static QString encodeSldBrushStyle(Qt::BrushStyle style)
static Qt::PenJoinStyle decodePenJoinStyle(const QString &str)
static QgsArrowSymbolLayer::HeadType decodeArrowHeadType(const QVariant &value, bool *ok=nullptr)
Decodes a value representing an arrow head type.
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
static Q_DECL_DEPRECATED QSet< const QgsSymbolLayer * > toSymbolLayerPointers(const QgsFeatureRenderer *renderer, const QSet< QgsSymbolLayerId > &symbolLayerIds)
Converts a set of symbol layer id to a set of pointers to actual symbol layers carried by the feature...
static QVariant colorRampToVariant(const QString &name, QgsColorRamp *ramp)
Saves a color ramp to a QVariantMap, wrapped in a QVariant.
static void applyScaleDependency(QDomDocument &doc, QDomElement &ruleElem, QVariantMap &props)
Checks if the properties contain scaleMinDenom and scaleMaxDenom, if available, they are added into t...
static QgsStringMap evaluatePropertiesMap(const QMap< QString, QgsProperty > &propertiesMap, const QgsExpressionContext &context)
Evaluates a map of properties using the given context and returns a variant map with evaluated expres...
static void drawVertexMarker(double x, double y, QPainter &p, Qgis::VertexMarkerType type, int markerSize)
Draws a vertex symbol at (painter) coordinates x, y.
static bool createExpressionElement(QDomDocument &doc, QDomElement &element, const QString &function)
Creates a OGC Expression element based on the provided function expression.
static bool displacementFromSldElement(QDomElement &element, QPointF &offset)
static bool hasWellKnownMark(QDomElement &element)
static std::unique_ptr< QgsColorRamp > loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
static QString getSvgParametricPath(const QString &basePath, const QColor &fillColor, const QColor &strokeColor, double strokeWidth)
Encodes a reference to a parametric SVG into a path with parameters according to the SVG Parameters s...
static bool createFunctionElement(QDomDocument &doc, QDomElement &element, const QString &function)
static QColor decodeColor(const QString &str)
static std::unique_ptr< QgsSymbolLayer > loadSymbolLayer(QDomElement &element, const QgsReadWriteContext &context)
Reads and returns symbol layer from XML. Caller is responsible for deleting the returned object.
static bool onlineResourceFromSldElement(QDomElement &element, QString &path, QString &format)
static QPointF polygonCentroid(const QPolygonF &points)
Calculate the centroid point of a QPolygonF.
static QIcon colorRampPreviewIcon(QgsColorRamp *ramp, QSize size, int padding=0)
Returns an icon preview for a color ramp.
static QString encodeBrushStyle(Qt::BrushStyle style)
static QString svgSymbolPathToName(const QString &path, const QgsPathResolver &pathResolver)
Determines an SVG symbol's name from its path.
static QPixmap colorRampPreviewPixmap(QgsColorRamp *ramp, QSize size, int padding=0, Qt::Orientation direction=Qt::Horizontal, bool flipDirection=false, bool drawTransparentBackground=true)
Returns a pixmap preview for a color ramp.
static QString encodeSldAlpha(int alpha)
static void externalGraphicToSld(QDomDocument &doc, QDomElement &element, const QString &path, const QString &mime, const QColor &color, double size=-1)
static QPointF polygonPointOnSurface(const QPolygonF &points, const QVector< QPolygonF > *rings=nullptr)
Calculate a point on the surface of a QPolygonF.
static void blurImageInPlace(QImage &image, QRect rect, int radius, bool alphaOnly)
Blurs an image in place, e.g. creating Qt-independent drop shadows.
static QList< double > prettyBreaks(double minimum, double maximum, int classes)
Computes a sequence of about 'classes' equally spaced round values which cover the range of values fr...
static QPointF toPoint(const QVariant &value, bool *ok=nullptr)
Converts a value to a point.
static void premultiplyColor(QColor &rgb, int alpha)
Converts a QColor into a premultiplied ARGB QColor value using a specified alpha value.
static void saveProperties(QVariantMap props, QDomDocument &doc, QDomElement &element)
Saves the map of properties to XML.
static void multiplyImageOpacity(QImage *image, qreal opacity)
Multiplies opacity of image pixel values with a (global) transparency value.
static bool functionFromSldElement(QDomElement &element, QString &function)
static bool saveColorsToGpl(QFile &file, const QString &paletteName, const QgsNamedColorList &colors)
Exports colors to a gpl GIMP palette file.
static std::unique_ptr< QgsSymbolLayer > createFillLayerFromSld(QDomElement &element)
Creates a new fill layer from a SLD DOM element.
static QColor parseColorWithAlpha(const QString &colorStr, bool &containsAlpha, bool strictEval=false)
Attempts to parse a string as a color using a variety of common formats, including hex codes,...
static bool hasSldSymbolizer(const QDomElement &element)
Returns true if a DOM element contains an SLD Symbolizer element.
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
static QSizeF toSize(const QVariant &value, bool *ok=nullptr)
Converts a value to a size.
static double rescaleUom(double size, Qgis::RenderUnit unit, const QVariantMap &props)
Rescales the given size based on the uomScale found in the props, if any is found,...
static bool needEllipseMarker(QDomElement &element)
static std::unique_ptr< QgsSymbolLayer > createMarkerLayerFromSld(QDomElement &element)
Creates a new marker layer from a SLD DOM element.
static QgsNamedColorList colorListFromMimeData(const QMimeData *data)
Attempts to parse mime data as a list of named colors.
static void clearSymbolLayerMasks(QgsSymbol *symbol)
Remove recursively masks from all symbol symbol layers.
static bool isSharpCorner(QPointF p1, QPointF p2, QPointF p3)
Returns true if the angle formed by the line p1 - p2 - p3 forms a "sharp" corner.
static QString ogrFeatureStylePen(double width, double mmScaleFactor, double mapUnitsScaleFactor, const QColor &c, Qt::PenJoinStyle joinStyle=Qt::MiterJoin, Qt::PenCapStyle capStyle=Qt::FlatCap, double offset=0.0, const QVector< qreal > *dashPattern=nullptr)
Create ogr feature style string for pen.
static Qt::PenCapStyle decodePenCapStyle(const QString &str)
static double rendererFrameRate(const QgsFeatureRenderer *renderer)
Calculates the frame rate (in frames per second) at which the given renderer must be redrawn.
static QgsStringMap getSvgParameterList(QDomElement &element)
static bool needSvgFill(QDomElement &element)
static bool createSymbolLayerListFromSld(QDomElement &element, Qgis::GeometryType geomType, QList< QgsSymbolLayer * > &layers)
Creates a symbol layer list from a DOM element.
static bool externalGraphicFromSld(QDomElement &element, QString &path, QString &mime, QColor &color, double &size)
static void parametricSvgToSld(QDomDocument &doc, QDomElement &graphicElem, const QString &path, const QColor &fillColor, double size, const QColor &strokeColor, double strokeWidth)
Encodes a reference to a parametric SVG into SLD, as a succession of parametric SVG using URL paramet...
static QIcon symbolLayerPreviewIcon(const QgsSymbolLayer *layer, Qgis::RenderUnit u, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::SymbolType parentSymbolType=Qgis::SymbolType::Hybrid, QgsMapLayer *mapLayer=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Draws a symbol layer preview to an icon.
static QString encodeSldLineCapStyle(Qt::PenCapStyle style)
static QString encodeSldUom(Qgis::RenderUnit unit, double *scaleFactor)
Encodes a render unit into an SLD unit of measure string.
static QList< QList< QPolygonF > > toQPolygonF(const QgsGeometry &geometry, Qgis::SymbolType type)
Converts a geometry to a set of QPolygonF objects representing how the geometry should be drawn for a...
static std::unique_ptr< QgsSymbol > loadSymbol(const QDomElement &element, const QgsReadWriteContext &context)
Attempts to load a symbol from a DOM element.
static QVector< qreal > decodeRealVector(const QString &s)
static bool lineFromSld(QDomElement &element, Qt::PenStyle &penStyle, QColor &color, double &width, Qt::PenJoinStyle *penJoinStyle=nullptr, Qt::PenCapStyle *penCapStyle=nullptr, QVector< qreal > *customDashPattern=nullptr, double *dashOffset=nullptr)
static QPainter::CompositionMode decodeBlendMode(const QString &s)
static Qgis::ScaleMethod decodeScaleMethod(const QString &str)
Decodes a symbol scale method from a string.
static void createOpacityElement(QDomDocument &doc, QDomElement &element, const QString &alphaFunc)
static std::unique_ptr< QgsSymbolLayer > createLineLayerFromSld(QDomElement &element)
Creates a new line layer from a SLD DOM element.
static QString ogrFeatureStyleBrush(const QColor &fillColr)
Create ogr feature style string for brush.
static bool pointInPolygon(const QPolygonF &points, QPointF point)
Calculate whether a point is within of a QPolygonF.
static QStringList listSvgFiles()
Returns a list of all available svg files.
static QString encodeLineClipMode(Qgis::LineClipMode mode)
Encodes a line clip mode to a string.
static QPixmap symbolPreviewPixmap(const QgsSymbol *symbol, QSize size, int padding=0, QgsRenderContext *customContext=nullptr, bool selected=false, const QgsExpressionContext *expressionContext=nullptr, const QgsLegendPatchShape *shape=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Returns a pixmap preview for a color ramp.
static bool convertPolygonSymbolizerToPointMarker(QDomElement &element, QList< QgsSymbolLayer * > &layerList)
Converts a polygon symbolizer element to a list of marker symbol layers.
static Qgis::LineClipMode decodeLineClipMode(const QString &string, bool *ok=nullptr)
Decodes a string representing a line clip mode.
static QStringList listSvgFilesAt(const QString &directory)
Returns a list of svg files at the specified directory.
static bool needFontMarker(QDomElement &element)
static QString encodePenCapStyle(Qt::PenCapStyle style)
static QPointF pointOnLineWithDistance(QPointF startPoint, QPointF directionPoint, double distance)
Returns a point on the line from startPoint to directionPoint that is a certain distance away from th...
static QFont::Style decodeSldFontStyle(const QString &str)
static QSize tileSize(int width, int height, double &angleRad)
Calculate the minimum size in pixels of a symbol tile given the symbol width and height and the symbo...
static QString fieldOrExpressionFromExpression(QgsExpression *expression)
Returns a field name if the whole expression is just a name of the field .
static bool opacityFromSldElement(QDomElement &element, QString &alphaFunc)
static QString encodeSldFontWeight(int weight)
static 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)
Extracts properties from an SLD marker definition.
static void mergeScaleDependencies(double mScaleMinDenom, double mScaleMaxDenom, QVariantMap &props)
Merges the local scale limits, if any, with the ones already in the map, if any.
static QgsSymbol * restrictedSizeSymbol(const QgsSymbol *s, double minSize, double maxSize, QgsRenderContext *context, double &width, double &height, bool *ok=nullptr)
Creates a new symbol with size restricted to min/max size if original size is out of min/max range.
static QString colorToName(const QColor &color)
Returns a friendly display name for a color.
static int decodeSldAlpha(const QString &str)
static QString encodeSldLineJoinStyle(Qt::PenJoinStyle style)
static void createDisplacementElement(QDomDocument &doc, QDomElement &element, QPointF offset)
static QString svgSymbolNameToPath(const QString &name, const QgsPathResolver &pathResolver)
Determines an SVG symbol's path from its name.
static void drawStippledBackground(QPainter *painter, QRect rect)
static QList< QColor > parseColorList(const QString &colorStr)
Attempts to parse a string as a list of colors using a variety of common formats, including hex codes...
static QString encodeColor(const QColor &color)
static Qt::PenJoinStyle decodeSldLineJoinStyle(const QString &str)
static QVariantMap parseProperties(const QDomElement &element)
Parses the properties from XML and returns a map.
static bool fillFromSld(QDomElement &element, Qt::BrushStyle &brushStyle, QColor &color)
static Qgis::EndCapStyle penCapStyleToEndCapStyle(Qt::PenCapStyle style)
Converts a Qt pen cap style to a QGIS end cap style.
static QMimeData * symbolToMimeData(const QgsSymbol *symbol)
Creates new mime data from a symbol.
static QString encodeSldFontStyle(QFont::Style style)
static QColor colorFromMimeData(const QMimeData *data, bool &hasAlpha)
Attempts to parse mime data as a color.
static int decodeSldFontWeight(const QString &str)
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
static 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 QDomElement saveColorRamp(const QString &name, const QgsColorRamp *ramp, QDomDocument &doc)
Encodes a color ramp's settings to an XML element.
static Qgis::RenderUnit decodeSldUom(const QString &str, double *scaleFactor=nullptr)
Decodes a SLD unit of measure string to a render unit.
static 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 QDomElement saveSymbols(QgsSymbolMap &symbols, const QString &tagName, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a collection of symbols to XML with specified tagName for the top-level element.
static std::unique_ptr< QgsExpression > fieldOrExpressionToExpression(const QString &fieldOrExpression)
Returns a new valid expression instance for given field or expression string.
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
static QgsStringMap getVendorOptionList(QDomElement &element)
static Qgis::JoinStyle penJoinStyleToJoinStyle(Qt::PenJoinStyle style)
Converts a Qt pen joinstyle to a QGIS join style.
static QIcon symbolPreviewIcon(const QgsSymbol *symbol, QSize size, int padding=0, QgsLegendPatchShape *shape=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Returns an icon preview for a color ramp.
static QMimeData * colorToMimeData(const QColor &color)
Creates mime data from a color.
static bool condenseFillAndOutline(QgsFillSymbolLayer *fill, QgsLineSymbolLayer *outline)
Attempts to condense a fill and outline layer, by moving the outline layer to the fill symbol's strok...
static QPointF decodePoint(const QString &string)
Decodes a QSizeF from a string.
static QPolygonF polylineSubstring(const QPolygonF &polyline, double startOffset, double endOffset)
Returns the substring of a polyline which starts at startOffset from the beginning of the line and en...
static bool needPointPatternFill(QDomElement &element)
static QString encodeSldRealVector(const QVector< qreal > &v)
static QString encodeCoordinateReference(Qgis::SymbolCoordinateReference coordinateReference)
Encodes a symbol coordinate reference mode to a string.
static bool needRasterImageFill(QDomElement &element)
Checks if element contains a graphic fill with a raster image of type PNG, JPEG or GIF.
static QDomElement createSvgParameterElement(QDomDocument &doc, const QString &name, const QString &value)
static QString encodeMarkerClipMode(Qgis::MarkerClipMode mode)
Encodes a marker clip mode to a string.
static QSizeF decodeSize(const QString &string)
Decodes a QSizeF from a string.
static QString encodeRealVector(const QVector< qreal > &v)
Abstract base class for symbol layers.
virtual QgsSymbolLayer * clone() const =0
Shall be reimplemented by subclasses to create a deep copy of the instance.
virtual bool setSubSymbol(QgsSymbol *symbol)
Sets layer's subsymbol. takes ownership of the passed symbol.
void setId(const QString &id)
Set symbol layer identifier This id has to be unique in the whole project.
bool isLocked() const
Returns true if the symbol layer colors are locked and the layer will ignore any symbol-level color c...
Property
Data definable properties.
virtual double estimateMaxBleed(const QgsRenderContext &context) const
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the layer.
virtual QVariantMap properties() const =0
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
bool enabled() const
Returns true if symbol layer is enabled and will be drawn.
virtual QString layerType() const =0
Returns a string that represents this layer type.
int renderingPass() const
Specifies the rendering pass in which this symbol layer should be rendered.
QString id() const
Returns symbol layer identifier This id is unique in the whole project.
virtual QgsSymbol * subSymbol()
Returns the symbol's sub symbol, if present.
Qgis::SymbolLayerUserFlags userFlags() const
Returns user-controlled flags which control the symbol layer's behavior.
virtual QColor color() const
Returns the "representative" color of the symbol layer.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol layer property definitions.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
virtual bool hasDataDefinedProperties() const
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
Encapsulates the context in which a symbol is being rendered.
void setOriginalGeometryType(Qgis::GeometryType type)
Sets the geometry type for the original feature geometry being rendered.
Abstract base class for all rendered symbols.
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol's property collection, used for data defined overrides.
QgsSymbolAnimationSettings & animationSettings()
Returns a reference to the symbol animation settings.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol property definitions.
Qgis::SymbolFlags flags() const
Returns flags for the symbol.
qreal opacity() const
Returns the opacity for the symbol.
bool clipFeaturesToExtent() const
Returns whether features drawn by the symbol will be clipped to the render context's extent.
QgsSymbolBufferSettings * bufferSettings()
Returns the symbol buffer settings, which control an optional "halo" effect around the symbol.
bool hasDataDefinedProperties() const
Returns whether the symbol utilizes any data defined properties.
QgsSymbolLayerList symbolLayers() const
Returns the list of symbol layers contained in the symbol.
Qgis::RenderUnit extentBufferSizeUnit() const
Returns the units for the buffer size.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
QColor color() const
Returns the symbol's color.
Qgis::SymbolType type() const
Returns the symbol's type.
double extentBuffer() const
Returns the symbol's extent buffer.
bool forceRHR() const
Returns true if polygon features drawn by the symbol will be reoriented to follow the standard right-...
static Q_INVOKABLE Qgis::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
static Qgis::GeometryType geometryType(Qgis::WkbType type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement.
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsVariantLessThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is less than the second.
bool qgsVariantGreaterThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is greater than the second.
#define Q_NOWARN_DEPRECATED_POP
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
QString qgsFlagValueToKeys(const T &value, bool *returnOk=nullptr)
Returns the value for the given keys of a flag.
T qgsFlagKeysToValue(const QString &keys, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given keys of a flag.
#define Q_NOWARN_DEPRECATED_PUSH
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QVector< QgsPolylineXY > QgsPolygonXY
Polygon: first item of the list is outer ring, inner rings (if any) start from second item.
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)
QList< QgsSymbolLayer * > QgsSymbolLayerList
QList< QPolygonF > offsetLine(QPolygonF polyline, double dist, Qgis::GeometryType geometryType)
calculate geometry shifted by a specified distance
QPolygonF lineStringToQPolygonF(const QgsLineString *line)
QPolygonF curveToPolygonF(const QgsCurve *curve)
void changeSymbolLayerIds(QgsSymbolLayer *sl, Functor &&generateId)
QList< QPair< QColor, QString > > QgsNamedColorList
QMap< QString, QgsSymbol * > QgsSymbolMap
QMap< QString, QString > QgsStringMap
Contains information relating to a node (i.e.
QString identifier
A string identifying the node.
QgsStyleEntityVisitorInterface::NodeType type
Node type.
Contains information relating to the style entity currently being visited.
const QgsStyleEntityInterface * entity
Reference to style entity being visited.
QString identifier
A string identifying the style entity.