52#include <QDomDocument>
60#include <QRegularExpression>
66#define POINTS_TO_MM 2.83464567
70 return u
"%1,%2,%3,%4"_s.arg( color.red() ).arg( color.green() ).arg( color.blue() ).arg( color.alpha() );
75 const QStringList lst = str.split(
',' );
76 if ( lst.count() < 3 )
80 int red, green, blue, alpha;
82 green = lst[1].toInt();
83 blue = lst[2].toInt();
85 if ( lst.count() > 3 )
87 alpha = lst[3].toInt();
89 return QColor( red, green, blue, alpha );
94 return QString::number( alpha / 255.0,
'g', 2 );
100 double alpha = str.toDouble( &ok );
101 if ( !ok || alpha > 1 )
103 else if ( alpha < 0 )
112 case QFont::StyleNormal:
114 case QFont::StyleItalic:
116 case QFont::StyleOblique:
125 if ( str ==
"normal"_L1 )
return QFont::StyleNormal;
126 if ( str ==
"italic"_L1 )
return QFont::StyleItalic;
127 if ( str ==
"oblique"_L1 )
return QFont::StyleOblique;
128 return QFont::StyleNormal;
133 if ( weight == 50 )
return u
"normal"_s;
134 if ( weight == 75 )
return u
"bold"_s;
138 if ( weight < 0 )
return u
"100"_s;
139 if ( weight > 99 )
return u
"900"_s;
140 return QString::number( weight * 800 / 99 + 100 );
146 const int weight = str.toInt( &ok );
148 return static_cast< int >( QFont::Normal );
152 if ( weight > 900 )
return 99;
153 if ( weight < 100 )
return 0;
154 return ( weight - 100 ) * 99 / 800;
169 case Qt::DashDotLine:
170 return u
"dash dot"_s;
171 case Qt::DashDotDotLine:
172 return u
"dash dot dot"_s;
180 if ( str ==
"no"_L1 )
return Qt::NoPen;
181 if ( str ==
"solid"_L1 )
return Qt::SolidLine;
182 if ( str ==
"dash"_L1 )
return Qt::DashLine;
183 if ( str ==
"dot"_L1 )
return Qt::DotLine;
184 if ( str ==
"dash dot"_L1 )
return Qt::DashDotLine;
185 if ( str ==
"dash dot dot"_L1 )
return Qt::DashDotDotLine;
186 return Qt::SolidLine;
206 const QString cleaned = str.toLower().trimmed();
207 if ( cleaned ==
"bevel"_L1 )
208 return Qt::BevelJoin;
209 if ( cleaned ==
"miter"_L1 )
210 return Qt::MiterJoin;
211 if ( cleaned ==
"round"_L1 )
212 return Qt::RoundJoin;
213 return Qt::BevelJoin;
233 if ( str ==
"bevel"_L1 )
return Qt::BevelJoin;
234 if ( str ==
"mitre"_L1 )
return Qt::MiterJoin;
235 if ( str ==
"round"_L1 )
return Qt::RoundJoin;
236 return Qt::BevelJoin;
256 if ( str ==
"square"_L1 )
return Qt::SquareCap;
257 if ( str ==
"flat"_L1 )
return Qt::FlatCap;
258 if ( str ==
"round"_L1 )
return Qt::RoundCap;
259 return Qt::SquareCap;
279 if ( str ==
"square"_L1 )
return Qt::SquareCap;
280 if ( str ==
"butt"_L1 )
return Qt::FlatCap;
281 if ( str ==
"round"_L1 )
return Qt::RoundCap;
282 return Qt::SquareCap;
289 case Qt::SolidPattern :
291 case Qt::HorPattern :
292 return u
"horizontal"_s;
293 case Qt::VerPattern :
294 return u
"vertical"_s;
295 case Qt::CrossPattern :
297 case Qt::BDiagPattern :
298 return u
"b_diagonal"_s;
299 case Qt::FDiagPattern :
300 return u
"f_diagonal"_s;
301 case Qt::DiagCrossPattern :
302 return u
"diagonal_x"_s;
303 case Qt::Dense1Pattern :
305 case Qt::Dense2Pattern :
307 case Qt::Dense3Pattern :
309 case Qt::Dense4Pattern :
311 case Qt::Dense5Pattern :
313 case Qt::Dense6Pattern :
315 case Qt::Dense7Pattern :
326 if ( str ==
"solid"_L1 )
return Qt::SolidPattern;
327 if ( str ==
"horizontal"_L1 )
return Qt::HorPattern;
328 if ( str ==
"vertical"_L1 )
return Qt::VerPattern;
329 if ( str ==
"cross"_L1 )
return Qt::CrossPattern;
330 if ( str ==
"b_diagonal"_L1 )
return Qt::BDiagPattern;
331 if ( str ==
"f_diagonal"_L1 )
return Qt::FDiagPattern;
332 if ( str ==
"diagonal_x"_L1 )
return Qt::DiagCrossPattern;
333 if ( str ==
"dense1"_L1 )
return Qt::Dense1Pattern;
334 if ( str ==
"dense2"_L1 )
return Qt::Dense2Pattern;
335 if ( str ==
"dense3"_L1 )
return Qt::Dense3Pattern;
336 if ( str ==
"dense4"_L1 )
return Qt::Dense4Pattern;
337 if ( str ==
"dense5"_L1 )
return Qt::Dense5Pattern;
338 if ( str ==
"dense6"_L1 )
return Qt::Dense6Pattern;
339 if ( str ==
"dense7"_L1 )
return Qt::Dense7Pattern;
340 if ( str ==
"no"_L1 )
return Qt::NoBrush;
341 return Qt::SolidPattern;
348 case Qt::CrossPattern:
350 case Qt::DiagCrossPattern:
361 case Qt::BDiagPattern:
363 case Qt::FDiagPattern:
364 return u
"backslash"_s;
367 case Qt::Dense1Pattern:
368 case Qt::Dense2Pattern:
369 case Qt::Dense3Pattern:
370 case Qt::Dense4Pattern:
371 case Qt::Dense5Pattern:
372 case Qt::Dense6Pattern:
373 case Qt::Dense7Pattern:
383 if ( str ==
"horline"_L1 )
return Qt::HorPattern;
384 if ( str ==
"line"_L1 )
return Qt::VerPattern;
385 if ( str ==
"cross"_L1 )
return Qt::CrossPattern;
386 if ( str ==
"slash"_L1 )
return Qt::BDiagPattern;
387 if ( str ==
"backshash"_L1 )
return Qt::FDiagPattern;
388 if ( str ==
"x"_L1 )
return Qt::DiagCrossPattern;
390 if ( str.startsWith(
"brush://"_L1 ) )
406 case Qt::MPenCapStyle:
419 case Qt::SvgMiterJoin:
425 case Qt::MPenJoinStyle:
434 const QDomNodeList children = element.childNodes();
435 for (
int i = 0; i < children.size(); ++i )
437 const QDomElement childElement = children.at( i ).toElement();
438 if ( childElement.tagName() ==
"se:LineSymbolizer"_L1
439 || childElement.tagName() ==
"se:PointSymbolizer"_L1
440 || childElement.tagName() ==
"se:PolygonSymbolizer"_L1 )
448 const QString compareString =
string.trimmed();
452 if ( compareString.compare(
"feature"_L1, Qt::CaseInsensitive ) == 0 )
454 else if ( compareString.compare(
"viewport"_L1, Qt::CaseInsensitive ) == 0 )
464 switch ( coordinateReference )
469 return u
"viewport"_s;
480 const QString s = value.toString().toLower().trimmed();
481 if ( s ==
"single"_L1 )
483 else if ( s ==
"reversed"_L1 )
485 else if ( s ==
"double"_L1 )
487 else if ( value.toInt() == 1 )
489 else if ( value.toInt() == 2 )
491 else if ( value.toInt( &intOk ) == 0 && intOk )
505 const QString s = value.toString().toLower().trimmed();
506 if ( s ==
"plain"_L1 )
508 else if ( s ==
"lefthalf"_L1 )
510 else if ( s ==
"righthalf"_L1 )
512 else if ( value.toInt() == 1 )
514 else if ( value.toInt() == 2 )
516 else if ( value.toInt( &intOk ) == 0 && intOk )
526 const QString compareString =
string.trimmed();
530 if ( compareString.compare(
"no"_L1, Qt::CaseInsensitive ) == 0 )
532 else if ( compareString.compare(
"shape"_L1, Qt::CaseInsensitive ) == 0 )
534 else if ( compareString.compare(
"centroid_within"_L1, Qt::CaseInsensitive ) == 0 )
536 else if ( compareString.compare(
"completely_within"_L1, Qt::CaseInsensitive ) == 0 )
553 return u
"centroid_within"_s;
555 return u
"completely_within"_s;
562 const QString compareString =
string.trimmed();
566 if ( compareString.compare(
"no"_L1, Qt::CaseInsensitive ) == 0 )
568 else if ( compareString.compare(
"during_render"_L1, Qt::CaseInsensitive ) == 0 )
570 else if ( compareString.compare(
"before_render"_L1, Qt::CaseInsensitive ) == 0 )
585 return u
"during_render"_s;
587 return u
"before_render"_s;
599 QStringList lst = str.split(
',' );
600 if ( lst.count() != 2 )
601 return QPointF( 0, 0 );
602 return QPointF( lst[0].toDouble(), lst[1].toDouble() );
613 if ( value.userType() == QMetaType::Type::QVariantList )
615 const QVariantList list = value.toList();
616 if ( list.size() != 2 )
620 bool convertOk =
false;
621 const double x = list.at( 0 ).toDouble( &convertOk );
624 const double y = list.at( 1 ).toDouble( &convertOk );
629 return QPointF( x, y );
637 const QStringList list = value.toString().trimmed().split(
',' );
638 if ( list.count() != 2 )
640 bool convertOk =
false;
641 const double x = list.at( 0 ).toDouble( &convertOk );
644 const double y = list.at( 1 ).toDouble( &convertOk );
649 return QPointF( x, y );
663 QStringList lst =
string.split(
',' );
664 if ( lst.count() != 2 )
665 return QSizeF( 0, 0 );
666 return QSizeF( lst[0].toDouble(), lst[1].toDouble() );
677 if ( value.userType() == QMetaType::Type::QVariantList )
679 const QVariantList list = value.toList();
680 if ( list.size() != 2 )
684 bool convertOk =
false;
685 const double x = list.at( 0 ).toDouble( &convertOk );
688 const double y = list.at( 1 ).toDouble( &convertOk );
693 return QSizeF( x, y );
701 const QStringList list = value.toString().trimmed().split(
',' );
702 if ( list.count() != 2 )
704 bool convertOk =
false;
705 const double x = list.at( 0 ).toDouble( &convertOk );
708 const double y = list.at( 1 ).toDouble( &convertOk );
713 return QSizeF( x, y );
734 if ( str.startsWith(
"3x:"_L1 ) )
737 const QString chopped = str.mid( 3 );
738 lst = chopped.split(
',' );
742 lst = str.split(
',' );
744 if ( lst.count() < 2 )
747 double minScale = lst[0].toDouble();
749 minScale = minScale != 0 ? 1.0 / minScale : 0;
750 double maxScale = lst[1].toDouble();
752 maxScale = maxScale != 0 ? 1.0 / maxScale : 0;
754 if ( lst.count() < 6 )
774 *scaleFactor = 0.001;
775 return u
"http://www.opengeospatial.org/se/units/metre"_s;
780 return u
"http://www.opengeospatial.org/se/units/metre"_s;
787 *scaleFactor = 1 / 0.28;
796 if ( str ==
"http://www.opengeospatial.org/se/units/metre"_L1 )
802 else if ( str ==
"http://www.opengeospatial.org/se/units/foot"_L1 )
805 *scaleFactor = 0.3048;
820 QString vectorString;
821 QVector<qreal>::const_iterator it = v.constBegin();
822 for ( ; it != v.constEnd(); ++it )
824 if ( it != v.constBegin() )
826 vectorString.append(
';' );
828 vectorString.append( QString::number( *it ) );
835 QVector<qreal> resultVector;
837 const QStringList realList = s.split(
';' );
838 QStringList::const_iterator it = realList.constBegin();
839 for ( ; it != realList.constEnd(); ++it )
841 resultVector.append( it->toDouble() );
849 QString vectorString;
850 QVector<qreal>::const_iterator it = v.constBegin();
851 for ( ; it != v.constEnd(); ++it )
853 if ( it != v.constBegin() )
855 vectorString.append(
' ' );
857 vectorString.append( QString::number( *it ) );
864 QVector<qreal> resultVector;
866 const QStringList realList = s.split(
' ' );
867 QStringList::const_iterator it = realList.constBegin();
868 for ( ; it != realList.constEnd(); ++it )
870 resultVector.append( it->toDouble() );
878 QString encodedValue;
880 switch ( scaleMethod )
883 encodedValue = u
"diameter"_s;
886 encodedValue = u
"area"_s;
896 if ( str ==
"diameter"_L1 )
910 if ( s.compare(
"Lighten"_L1, Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Lighten;
911 if ( s.compare(
"Screen"_L1, Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Screen;
912 if ( s.compare(
"Dodge"_L1, Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorDodge;
913 if ( s.compare(
"Addition"_L1, Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Plus;
914 if ( s.compare(
"Darken"_L1, Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Darken;
915 if ( s.compare(
"Multiply"_L1, Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Multiply;
916 if ( s.compare(
"Burn"_L1, Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorBurn;
917 if ( s.compare(
"Overlay"_L1, Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Overlay;
918 if ( s.compare(
"SoftLight"_L1, Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_SoftLight;
919 if ( s.compare(
"HardLight"_L1, Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_HardLight;
920 if ( s.compare(
"Difference"_L1, Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Difference;
921 if ( s.compare(
"Subtract"_L1, Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Exclusion;
922 return QPainter::CompositionMode_SourceOver;
927 return QIcon(
symbolPreviewPixmap( symbol, size, padding,
nullptr,
false,
nullptr, shape, screen ) );
935 QPixmap pixmap( size * devicePixelRatio );
936 pixmap.setDevicePixelRatio( devicePixelRatio );
938 pixmap.fill( Qt::transparent );
940 painter.begin( &pixmap );
945 painter.setRenderHint( QPainter::Antialiasing );
946 painter.setRenderHint( QPainter::SmoothPixmapTransform );
956 size.setWidth( size.rwidth() - ( padding * 2 ) );
957 size.setHeight( size.rheight() - ( padding * 2 ) );
958 painter.translate( padding, padding );
968 std::unique_ptr<QgsSymbol> symbol_noDD( symbol->
clone( ) );
970 for (
const auto &layer : layers )
972 for (
int i = 0; i < layer->dataDefinedProperties().count(); ++i )
974 QgsProperty &prop = layer->dataDefinedProperties().property( i );
980 symbol_noDD->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape, screen );
984 std::unique_ptr<QgsSymbol> symbolClone( symbol->
clone( ) );
985 symbolClone->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape, screen );
999 maxBleed = layerMaxBleed > maxBleed ? layerMaxBleed : maxBleed;
1009 painter.begin( &picture );
1010 painter.setRenderHint( QPainter::Antialiasing );
1020 switch ( parentSymbolType )
1035 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
1036 layerClone->drawPreviewIcon( symbolContext, size );
1044 QPixmap pixmap( size * devicePixelRatio );
1045 pixmap.setDevicePixelRatio( devicePixelRatio );
1046 pixmap.fill( Qt::transparent );
1048 painter.begin( &pixmap );
1049 painter.setRenderHint( QPainter::Antialiasing );
1067 switch ( parentSymbolType )
1082 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
1083 layerClone->drawPreviewIcon( symbolContext, size );
1085 return QIcon( pixmap );
1095 QPixmap pixmap( size );
1096 pixmap.fill( Qt::transparent );
1099 painter.begin( &pixmap );
1102 if ( drawTransparentBackground )
1103 drawStippledBackground( &painter, QRect( padding, padding, size.width() - padding * 2, size.height() - padding * 2 ) );
1107 switch ( direction )
1109 case Qt::Horizontal:
1111 for (
int i = 0; i < size.width(); i++ )
1113 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.width() ) );
1114 painter.setPen( pen );
1115 const int x = flipDirection ? size.width() - i - 1 : i;
1116 painter.drawLine( x, 0 + padding, x, size.height() - 1 - padding );
1123 for (
int i = 0; i < size.height(); i++ )
1125 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.height() ) );
1126 painter.setPen( pen );
1127 const int y = flipDirection ? size.height() - i - 1 : i;
1128 painter.drawLine( 0 + padding, y, size.width() - 1 - padding, y );
1141 uchar pixDataRGB[] = { 255, 255, 255, 255,
1146 const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
1148 const int width = ( rect.width() < rect.height() ) ?
1149 rect.width() / 2.5 : rect.height() / 2.5;
1150 const QPixmap pix = QPixmap::fromImage( img.scaled( width, width ) );
1153 brush.setTexture( pix );
1154 painter->fillRect( rect, brush );
1159 const qreal s = ( markerSize - 1 ) / 2.0;
1164 p.setPen( QColor( 50, 100, 120, 200 ) );
1165 p.setBrush( QColor( 200, 200, 210, 120 ) );
1166 p.drawEllipse( x - s, y - s, s * 2, s * 2 );
1169 p.setPen( QColor( 255, 0, 0 ) );
1170 p.drawLine( x - s, y + s, x + s, y - s );
1171 p.drawLine( x - s, y - s, x + s, y + s );
1183static QPolygonF makeOffsetGeometry(
const QgsPolylineXY &polyline )
1185 int i, pointCount = polyline.count();
1187 QPolygonF resultLine;
1188 resultLine.resize( pointCount );
1192 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1193 resultLine[i] = QPointF( tempPtr->
x(), tempPtr->
y() );
1197static QList<QPolygonF> makeOffsetGeometry(
const QgsPolygonXY &polygon )
1199 QList<QPolygonF> resultGeom;
1200 resultGeom.reserve( polygon.size() );
1201 for (
int ring = 0; ring < polygon.size(); ++ring )
1202 resultGeom.append( makeOffsetGeometry( polygon[ ring ] ) );
1208 QList<QPolygonF> resultLine;
1210 if ( polyline.count() < 2 )
1212 resultLine.append( polyline );
1216 unsigned int i, pointCount = polyline.count();
1219 QPointF *tempPtr = polyline.data();
1220 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1221 tempPolyline[i] =
QgsPointXY( tempPtr->rx(), tempPtr->ry() );
1224 if ( !tempGeometry.
isNull() )
1226 const int quadSegments = 0;
1227 const double miterLimit = 2.0;
1235 if ( !offsetGeom.
isNull() )
1237 tempGeometry = offsetGeom;
1242 resultLine.append( makeOffsetGeometry( line ) );
1247 resultLine.append( makeOffsetGeometry( tempGeometry.
asPolygon() ) );
1253 resultLine.reserve( tempMPolyline.count() );
1254 for (
int part = 0; part < tempMPolyline.count(); ++part )
1256 resultLine.append( makeOffsetGeometry( tempMPolyline[ part ] ) );
1263 resultLine.reserve( tempMPolygon.count() );
1264 for (
int part = 0; part < tempMPolygon.count(); ++part )
1266 resultLine.append( makeOffsetGeometry( tempMPolygon[ part ] ) );
1274 resultLine.append( polyline );
1283 if ( element.isNull() )
1287 QDomNode layerNode = element.firstChild();
1289 while ( !layerNode.isNull() )
1291 QDomElement e = layerNode.toElement();
1292 if ( !e.isNull() && e.tagName() !=
"data_defined_properties"_L1 && e.tagName() !=
"buffer"_L1 )
1294 if ( e.tagName() !=
"layer"_L1 )
1300 std::unique_ptr< QgsSymbolLayer > layer =
loadSymbolLayer( e, context );
1304 const QDomElement s = e.firstChildElement( u
"symbol"_s );
1307 std::unique_ptr< QgsSymbol > subSymbol(
loadSymbol( s, context ) );
1314 layers.append( layer.release() );
1316 for (
int i = 0; i < subSymbol->symbolLayerCount(); ++i )
1318 layers.append( subSymbol->symbolLayer( i )->clone() );
1323 const bool res = layer->setSubSymbol( subSymbol.release() );
1326 QgsDebugError( u
"symbol layer refused subsymbol: "_s + s.attribute(
"name" ) );
1328 layers.append( layer.release() );
1333 layers.append( layer.release() );
1338 layerNode = layerNode.nextSibling();
1341 if ( layers.isEmpty() )
1347 const QString symbolType = element.attribute( u
"type"_s );
1349 std::unique_ptr< QgsSymbol > symbol;
1350 if ( symbolType ==
"line"_L1 )
1351 symbol = std::make_unique< QgsLineSymbol >( layers );
1352 else if ( symbolType ==
"fill"_L1 )
1353 symbol = std::make_unique< QgsFillSymbol >( layers );
1354 else if ( symbolType ==
"marker"_L1 )
1355 symbol = std::make_unique< QgsMarkerSymbol >( layers );
1362 if ( element.hasAttribute( u
"outputUnit"_s ) )
1366 if ( element.hasAttribute( ( u
"mapUnitScale"_s ) ) )
1369 const double oldMin = element.attribute( u
"mapUnitMinScale"_s, u
"0.0"_s ).toDouble();
1370 mapUnitScale.
minScale = oldMin != 0 ? 1.0 / oldMin : 0;
1371 const double oldMax = element.attribute( u
"mapUnitMaxScale"_s, u
"0.0"_s ).toDouble();
1372 mapUnitScale.
maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
1373 symbol->setMapUnitScale( mapUnitScale );
1375 symbol->setOpacity( element.attribute( u
"alpha"_s, u
"1.0"_s ).toDouble() );
1376 symbol->setExtentBuffer( element.attribute( u
"extent_buffer"_s, u
"0.0"_s ).toDouble() );
1378 symbol->setClipFeaturesToExtent( element.attribute( u
"clip_to_extent"_s, u
"1"_s ).toInt() );
1379 symbol->setForceRHR( element.attribute( u
"force_rhr"_s, u
"0"_s ).toInt() );
1381 if ( element.attribute( u
"renderer_should_use_levels"_s, u
"0"_s ).toInt() )
1383 symbol->setFlags( flags );
1385 symbol->animationSettings().setIsAnimated( element.attribute( u
"is_animated"_s, u
"0"_s ).toInt() );
1386 symbol->animationSettings().setFrameRate( element.attribute( u
"frame_rate"_s, u
"10"_s ).toDouble() );
1388 if ( !element.firstChildElement( u
"buffer"_s ).isNull() )
1390 auto bufferSettings = std::make_unique< QgsSymbolBufferSettings >();
1391 bufferSettings->readXml( element, context );
1392 symbol->setBufferSettings( bufferSettings.release() );
1396 symbol->setBufferSettings(
nullptr );
1399 const QDomElement ddProps = element.firstChildElement( u
"data_defined_properties"_s );
1400 if ( !ddProps.isNull() )
1410 const QString layerClass = element.attribute( u
"class"_s );
1411 const bool locked = element.attribute( u
"locked"_s ).toInt();
1412 const bool enabled = element.attribute( u
"enabled"_s, u
"1"_s ).toInt();
1413 const int pass = element.attribute( u
"pass"_s ).toInt();
1414 const QString
id = element.attribute( u
"id"_s );
1428 layer->setLocked( locked );
1429 layer->setRenderingPass( pass );
1430 layer->setEnabled( enabled );
1431 layer->setUserFlags( userFlags );
1434 if ( !
id.isEmpty() )
1438 const QDomElement effectElem = element.firstChildElement( u
"effect"_s );
1439 if ( !effectElem.isNull() )
1443 layer->setPaintEffect( effect.release() );
1447 const QDomElement ddProps = element.firstChildElement( u
"data_defined_properties"_s );
1448 if ( !ddProps.isNull() )
1455 const QSet< int > oldKeys = prevProperties.
propertyKeys();
1456 for (
int key : oldKeys )
1458 if ( !layer->dataDefinedProperties().propertyKeys().contains( key ) )
1490 QDomElement symEl = doc.createElement( u
"symbol"_s );
1491 symEl.setAttribute( u
"type"_s, _nameForSymbolType( symbol->
type() ) );
1492 symEl.setAttribute( u
"name"_s, name );
1493 symEl.setAttribute( u
"alpha"_s, QString::number( symbol->
opacity() ) );
1497 symEl.setAttribute( u
"extent_buffer"_s, QString::number( symbol->
extentBuffer() ) );
1500 symEl.setAttribute( u
"force_rhr"_s, symbol->
forceRHR() ? u
"1"_s : u
"0"_s );
1502 symEl.setAttribute( u
"renderer_should_use_levels"_s, u
"1"_s );
1508 bufferSettings->writeXml( symEl, context );
1512 QDomElement ddProps = doc.createElement( u
"data_defined_properties"_s );
1514 symEl.appendChild( ddProps );
1520 QDomElement layerEl = doc.createElement( u
"layer"_s );
1521 layerEl.setAttribute( u
"class"_s, layer->
layerType() );
1522 layerEl.setAttribute( u
"enabled"_s, layer->
enabled() );
1523 layerEl.setAttribute( u
"locked"_s, layer->
isLocked() );
1525 layerEl.setAttribute( u
"id"_s, layer->
id() );
1539 QDomElement ddProps = doc.createElement( u
"data_defined_properties"_s );
1541 layerEl.appendChild( ddProps );
1545 const QString subname = u
"@%1@%2"_s.arg( name ).arg( i );
1546 const QDomElement subEl =
saveSymbol( subname, subSymbol, doc, context );
1547 layerEl.appendChild( subEl );
1549 symEl.appendChild( layerEl );
1557 QDomDocument doc( u
"qgis-symbol-definition"_s );
1560 QTextStream stream( &props );
1561 symbolElem.save( stream, -1 );
1567 QList<QgsSymbolLayer *> &layers )
1571 if ( element.isNull() )
1574 const QString symbolizerName = element.localName();
1576 if ( symbolizerName ==
"PointSymbolizer"_L1 )
1579 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1580 if ( graphicElem.isNull() )
1582 QgsDebugError( u
"Graphic element not found in PointSymbolizer"_s );
1593 layers.append( l.release() );
1603 layers.append( l.release() );
1613 layers.append( l.release() );
1625 if ( symbolizerName ==
"LineSymbolizer"_L1 )
1628 const QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
1629 if ( strokeElem.isNull() )
1631 QgsDebugError( u
"Stroke element not found in LineSymbolizer"_s );
1644 layers.append( l.release() );
1654 layers.append( l.release() );
1666 if ( symbolizerName ==
"PolygonSymbolizer"_L1 )
1669 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
1670 const QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
1671 if ( fillElem.isNull() && strokeElem.isNull() )
1673 QgsDebugError( u
"neither Fill nor Stroke element not found in PolygonSymbolizer"_s );
1687 layers.append( l.release() );
1691 if ( lastLayer->
layerType() ==
"SimpleFill"_L1 || lastLayer->
layerType() ==
"SVGFill"_L1 )
1699 layers.append( l.release() );
1709 layers.append( l.release() );
1732 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
1733 if ( fillElem.isNull() )
1739 std::unique_ptr< QgsSymbolLayer > l;
1757 const QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
1758 if ( strokeElem.isNull() )
1764 std::unique_ptr< QgsSymbolLayer > l;
1776 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1777 if ( graphicElem.isNull() )
1783 std::unique_ptr< QgsSymbolLayer > l;
1806 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1807 if ( graphicElem.isNull() )
1810 const QDomElement externalGraphicElem = graphicElem.firstChildElement( u
"ExternalGraphic"_s );
1811 if ( externalGraphicElem.isNull() )
1815 const QDomElement formatElem = externalGraphicElem.firstChildElement( u
"Format"_s );
1816 if ( formatElem.isNull() )
1819 const QString elementFormat = formatElem.firstChild().nodeValue();
1820 if ( ! format.isEmpty() && elementFormat != format )
1822 QgsDebugMsgLevel(
"unsupported External Graphic format found: " + elementFormat, 4 );
1827 const QDomElement onlineResourceElem = externalGraphicElem.firstChildElement( u
"OnlineResource"_s );
1828 const QDomElement inlineContentElem = externalGraphicElem.firstChildElement( u
"InlineContent"_s );
1830 if ( !onlineResourceElem.isNull() )
1834 else if ( !inlineContentElem.isNull() )
1847 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1848 if ( graphicElem.isNull() )
1851 const QDomElement markElem = graphicElem.firstChildElement( u
"Mark"_s );
1852 if ( markElem.isNull() )
1855 const QDomElement wellKnownNameElem = markElem.firstChildElement( u
"WellKnownName"_s );
1856 return !wellKnownNameElem.isNull();
1862 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1863 if ( graphicElem.isNull() )
1866 const QDomElement markElem = graphicElem.firstChildElement( u
"Mark"_s );
1867 if ( markElem.isNull() )
1871 const QDomElement formatElem = markElem.firstChildElement( u
"Format"_s );
1872 if ( formatElem.isNull() )
1875 const QString format = formatElem.firstChild().nodeValue();
1876 if ( format !=
"ttf"_L1 )
1878 QgsDebugError(
"unsupported Graphic Mark format found: " + format );
1883 const QDomElement onlineResourceElem = markElem.firstChildElement( u
"OnlineResource"_s );
1884 const QDomElement inlineContentElem = markElem.firstChildElement( u
"InlineContent"_s );
1885 if ( !onlineResourceElem.isNull() )
1888 const QDomElement markIndexElem = markElem.firstChildElement( u
"MarkIndex"_s );
1889 if ( !markIndexElem.isNull() )
1892 else if ( !inlineContentElem.isNull() )
1913 QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1914 if ( graphicElem.isNull() )
1918 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
1920 if ( it.key() ==
"widthHeightFactor"_L1 )
1931 const QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
1932 if ( strokeElem.isNull() )
1935 QDomElement graphicStrokeElem = strokeElem.firstChildElement( u
"GraphicStroke"_s );
1936 if ( graphicStrokeElem.isNull() )
1944 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
1945 if ( fillElem.isNull() )
1948 const QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
1949 if ( graphicFillElem.isNull() )
1952 QDomElement graphicElem = graphicFillElem.firstChildElement( u
"Graphic"_s );
1953 if ( graphicElem.isNull() )
1959 QColor fillColor, strokeColor;
1960 double size, strokeWidth;
1961 Qt::PenStyle strokeStyle;
1962 if ( !
wellKnownMarkerFromSld( graphicElem, name, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
1965 if ( name !=
"horline"_L1 )
1973 const double angle = angleFunc.toDouble( &ok );
1979 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
1980 if ( fillElem.isNull() )
1983 const QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
1984 if ( graphicFillElem.isNull() )
1987 const QDomElement graphicElem = graphicFillElem.firstChildElement( u
"Graphic"_s );
1988 if ( graphicElem.isNull() )
1991 const QDomElement markElem = graphicElem.firstChildElement( u
"Mark"_s );
1992 if ( markElem.isNull() )
2000 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
2001 if ( fillElem.isNull() )
2004 QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
2005 if ( graphicFillElem.isNull() )
2013 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
2014 if ( fillElem.isNull() )
2017 QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
2018 if ( graphicFillElem.isNull() )
2038 QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
2039 QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
2043 bool validFill =
false, validStroke =
false;
2048 Qt::BrushStyle fillStyle;
2050 if (
fillFromSld( fillElem, fillStyle, fillColor ) )
2056 Qt::PenStyle strokeStyle;
2057 double strokeWidth = 1.0, dashOffset = 0.0;
2058 QVector<qreal> customDashPattern;
2060 if (
lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth,
2061 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2064 if ( validFill || validStroke )
2067 map[u
"name"_s] = u
"square"_s;
2070 map[u
"size"_s] = QString::number( 6 );
2071 map[u
"angle"_s] = QString::number( 0 );
2072 map[u
"offset"_s] =
encodePoint( QPointF( 0, 0 ) );
2079 bool validFill =
false, validStroke =
false;
2082 QString name, format;
2084 QColor fillColor, strokeColor;
2085 double strokeWidth = 1.0, size = 0.0, angle = 0.0;
2089 const QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
2090 if ( !graphicFillElem.isNull() )
2093 QDomElement graphicElem = graphicFillElem.firstChildElement( u
"Graphic"_s );
2094 if ( !graphicElem.isNull() )
2100 const QDomElement graphicChildElem = graphicElem.firstChildElement();
2101 while ( !graphicChildElem.isNull() )
2103 if ( graphicChildElem.localName() ==
"Mark"_L1 )
2106 const QDomElement wellKnownNameElem = graphicChildElem.firstChildElement( u
"WellKnownName"_s );
2107 if ( !wellKnownNameElem.isNull() )
2109 name = wellKnownNameElem.firstChild().nodeValue();
2115 if ( graphicChildElem.localName() ==
"ExternalGraphic"_L1 || graphicChildElem.localName() ==
"Mark"_L1 )
2118 const QDomElement formatElem = graphicChildElem.firstChildElement( u
"Format"_s );
2119 if ( formatElem.isNull() )
2122 format = formatElem.firstChild().nodeValue();
2126 if ( graphicChildElem.localName() ==
"ExternalGraphic"_L1 && format !=
"image/svg+xml"_L1 )
2131 if ( graphicChildElem.localName() ==
"Mark"_L1 && format !=
"ttf"_L1 )
2135 const QDomElement onlineResourceElem = graphicChildElem.firstChildElement( u
"OnlineResource"_s );
2136 const QDomElement inlineContentElem = graphicChildElem.firstChildElement( u
"InlineContent"_s );
2138 if ( !onlineResourceElem.isNull() )
2140 name = onlineResourceElem.attributeNS( u
"http://www.w3.org/1999/xlink"_s, u
"href"_s );
2142 if ( graphicChildElem.localName() ==
"Mark"_L1 && format ==
"ttf"_L1 )
2145 if ( name.startsWith(
"ttf://"_L1 ) )
2146 name = name.mid( 6 );
2149 const QDomElement markIndexElem = graphicChildElem.firstChildElement( u
"MarkIndex"_s );
2150 if ( markIndexElem.isNull() )
2154 const int v = markIndexElem.firstChild().nodeValue().toInt( &ok );
2165 else if ( !inlineContentElem.isNull() )
2175 if ( graphicChildElem.localName() ==
"Mark"_L1 )
2184 if ( found && graphicChildElem.localName() ==
"Mark"_L1 )
2191 Qt::BrushStyle markFillStyle;
2193 QDomElement markFillElem = graphicChildElem.firstChildElement( u
"Fill"_s );
2194 if (
fillFromSld( markFillElem, markFillStyle, fillColor ) )
2199 Qt::PenStyle strokeStyle;
2200 double strokeWidth = 1.0, dashOffset = 0.0;
2201 QVector<qreal> customDashPattern;
2203 QDomElement markStrokeElem = graphicChildElem.firstChildElement( u
"Stroke"_s );
2204 if (
lineFromSld( markStrokeElem, strokeStyle, strokeColor, strokeWidth,
2205 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2212 const QDomElement opacityElem = graphicElem.firstChildElement( u
"Opacity"_s );
2213 if ( !opacityElem.isNull() )
2214 fillColor.setAlpha(
decodeSldAlpha( opacityElem.firstChild().nodeValue() ) );
2216 const QDomElement sizeElem = graphicElem.firstChildElement( u
"Size"_s );
2217 if ( !sizeElem.isNull() )
2220 const double v = sizeElem.firstChild().nodeValue().toDouble( &ok );
2229 const double v = angleFunc.toDouble( &ok );
2239 if ( validFill || validStroke )
2241 if ( format ==
"image/svg+xml"_L1 )
2244 map[u
"name"_s] = name;
2245 map[u
"fill"_s] = fillColor.name();
2246 map[u
"outline"_s] = strokeColor.name();
2247 map[u
"outline-width"_s] = QString::number( strokeWidth );
2249 map[u
"size"_s] = QString::number( size );
2251 map[u
"angle"_s] = QString::number( angle );
2252 if ( !offset.isNull() )
2256 else if ( format ==
"ttf"_L1 )
2259 map[u
"font"_s] = name;
2260 map[u
"chr"_s] = markIndex;
2263 map[u
"size"_s] = QString::number( size );
2265 map[u
"angle"_s] = QString::number( angle );
2266 if ( !offset.isNull() )
2273 if ( layers.isEmpty() )
2276 layerList << layers;
2284 fillToSld( doc, element, context, brushStyle, color );
2289 QString patternName;
2290 switch ( brushStyle )
2295 case Qt::SolidPattern:
2296 if ( color.isValid() )
2299 if ( color.alpha() < 255 )
2304 case Qt::CrossPattern:
2305 case Qt::DiagCrossPattern:
2306 case Qt::HorPattern:
2307 case Qt::VerPattern:
2308 case Qt::BDiagPattern:
2309 case Qt::FDiagPattern:
2310 case Qt::Dense1Pattern:
2311 case Qt::Dense2Pattern:
2312 case Qt::Dense3Pattern:
2313 case Qt::Dense4Pattern:
2314 case Qt::Dense5Pattern:
2315 case Qt::Dense6Pattern:
2316 case Qt::Dense7Pattern:
2321 context.
pushWarning( QObject::tr(
"Brush style '%1' is not supported for SLD" ).arg( brushStyle ) );
2325 QDomElement graphicFillElem = doc.createElement( u
"se:GraphicFill"_s );
2326 element.appendChild( graphicFillElem );
2328 QDomElement graphicElem = doc.createElement( u
"se:Graphic"_s );
2329 graphicFillElem.appendChild( graphicElem );
2331 const QColor fillColor = patternName.startsWith(
"brush://"_L1 ) ? color : QColor();
2332 const QColor strokeColor = !patternName.startsWith(
"brush://"_L1 ) ? color : QColor();
2335 wellKnownMarkerToSld( doc, graphicElem, patternName, fillColor, strokeColor, Qt::SolidLine, context, -1, -1 );
2342 brushStyle = Qt::SolidPattern;
2343 color = QColor( 128, 128, 128 );
2345 if ( element.isNull() )
2347 brushStyle = Qt::NoBrush;
2352 const QDomElement graphicFillElem = element.firstChildElement( u
"GraphicFill"_s );
2354 if ( graphicFillElem.isNull() )
2357 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2359 QgsDebugMsgLevel( u
"found SvgParameter %1: %2"_s.arg( it.key(), it.value() ), 2 );
2361 if ( it.key() ==
"fill"_L1 )
2362 color = QColor( it.value() );
2363 else if ( it.key() ==
"fill-opacity"_L1 )
2369 QDomElement graphicElem = graphicFillElem.firstChildElement( u
"Graphic"_s );
2370 if ( graphicElem.isNull() )
2373 QString patternName = u
"square"_s;
2374 QColor fillColor, strokeColor;
2375 double strokeWidth, size;
2376 Qt::PenStyle strokeStyle;
2377 if ( !
wellKnownMarkerFromSld( graphicElem, patternName, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
2381 if ( brushStyle == Qt::NoBrush )
2384 const QColor
c = patternName.startsWith(
"brush://"_L1 ) ? fillColor : strokeColor;
2394 const Qt::PenJoinStyle *penJoinStyle,
const Qt::PenCapStyle *penCapStyle,
2395 const QVector<qreal> *customDashPattern,
double dashOffset )
2397 QVector<qreal> dashPattern;
2398 const QVector<qreal> *pattern = &dashPattern;
2400 if ( penStyle == Qt::CustomDashLine && !customDashPattern )
2402 context.
pushWarning( QObject::tr(
"WARNING: Custom dash pattern required but not provided. Using default dash pattern." ) );
2403 penStyle = Qt::DashLine;
2415 dashPattern.push_back( 4.0 );
2416 dashPattern.push_back( 2.0 );
2419 dashPattern.push_back( 1.0 );
2420 dashPattern.push_back( 2.0 );
2422 case Qt::DashDotLine:
2423 dashPattern.push_back( 4.0 );
2424 dashPattern.push_back( 2.0 );
2425 dashPattern.push_back( 1.0 );
2426 dashPattern.push_back( 2.0 );
2428 case Qt::DashDotDotLine:
2429 dashPattern.push_back( 4.0 );
2430 dashPattern.push_back( 2.0 );
2431 dashPattern.push_back( 1.0 );
2432 dashPattern.push_back( 2.0 );
2433 dashPattern.push_back( 1.0 );
2434 dashPattern.push_back( 2.0 );
2437 case Qt::CustomDashLine:
2438 Q_ASSERT( customDashPattern );
2439 pattern = customDashPattern;
2443 context.
pushWarning( QObject::tr(
"Pen style '%1' is not supported for SLD" ).arg( penStyle ) );
2447 if ( color.isValid() )
2450 if ( color.alpha() < 255 )
2457 else if ( width == 0 )
2467 if ( !pattern->isEmpty() )
2477 Qt::PenStyle &penStyle, QColor &color,
double &width,
2478 Qt::PenJoinStyle *penJoinStyle, Qt::PenCapStyle *penCapStyle,
2479 QVector<qreal> *customDashPattern,
double *dashOffset )
2483 penStyle = Qt::SolidLine;
2484 color = QColor( 0, 0, 0 );
2487 *penJoinStyle = Qt::BevelJoin;
2489 *penCapStyle = Qt::SquareCap;
2490 if ( customDashPattern )
2491 customDashPattern->clear();
2495 if ( element.isNull() )
2497 penStyle = Qt::NoPen;
2503 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2505 QgsDebugMsgLevel( u
"found SvgParameter %1: %2"_s.arg( it.key(), it.value() ), 2 );
2507 if ( it.key() ==
"stroke"_L1 )
2509 color = QColor( it.value() );
2511 else if ( it.key() ==
"stroke-opacity"_L1 )
2515 else if ( it.key() ==
"stroke-width"_L1 )
2518 const double w = it.value().toDouble( &ok );
2522 else if ( it.key() ==
"stroke-linejoin"_L1 && penJoinStyle )
2526 else if ( it.key() ==
"stroke-linecap"_L1 && penCapStyle )
2530 else if ( it.key() ==
"stroke-dasharray"_L1 )
2533 if ( !dashPattern.isEmpty() )
2537 bool dashPatternFound =
false;
2539 if ( dashPattern.count() == 2 )
2541 if ( dashPattern.at( 0 ) == 4.0 &&
2542 dashPattern.at( 1 ) == 2.0 )
2544 penStyle = Qt::DashLine;
2545 dashPatternFound =
true;
2547 else if ( dashPattern.at( 0 ) == 1.0 &&
2548 dashPattern.at( 1 ) == 2.0 )
2550 penStyle = Qt::DotLine;
2551 dashPatternFound =
true;
2554 else if ( dashPattern.count() == 4 )
2556 if ( dashPattern.at( 0 ) == 4.0 &&
2557 dashPattern.at( 1 ) == 2.0 &&
2558 dashPattern.at( 2 ) == 1.0 &&
2559 dashPattern.at( 3 ) == 2.0 )
2561 penStyle = Qt::DashDotLine;
2562 dashPatternFound =
true;
2565 else if ( dashPattern.count() == 6 )
2567 if ( dashPattern.at( 0 ) == 4.0 &&
2568 dashPattern.at( 1 ) == 2.0 &&
2569 dashPattern.at( 2 ) == 1.0 &&
2570 dashPattern.at( 3 ) == 2.0 &&
2571 dashPattern.at( 4 ) == 1.0 &&
2572 dashPattern.at( 5 ) == 2.0 )
2574 penStyle = Qt::DashDotDotLine;
2575 dashPatternFound =
true;
2580 if ( !dashPatternFound )
2582 if ( customDashPattern )
2584 penStyle = Qt::CustomDashLine;
2585 *customDashPattern = dashPattern;
2589 QgsDebugMsgLevel( u
"custom dash pattern required but not provided. Using default dash pattern."_s, 2 );
2590 penStyle = Qt::DashLine;
2595 else if ( it.key() ==
"stroke-dashoffset"_L1 && dashOffset )
2598 const double d = it.value().toDouble( &ok );
2608 const QString &path,
const QString &mime,
2609 const QColor &color,
double size )
2611 QDomElement externalGraphicElem = doc.createElement( u
"se:ExternalGraphic"_s );
2612 element.appendChild( externalGraphicElem );
2621 QDomElement sizeElem = doc.createElement( u
"se:Size"_s );
2623 element.appendChild( sizeElem );
2628 const QString &path,
const QColor &fillColor,
double size,
const QColor &strokeColor,
double strokeWidth )
2631 parametricSvgToSld( doc, graphicElem, path, fillColor, size, strokeColor, strokeWidth, context );
2641 graphicElem.appendChild( doc.createComment( u
"Parametric SVG"_s ) );
2642 const QString parametricPath =
getSvgParametricPath( path, fillColor, strokeColor, strokeWidth );
2645 graphicElem.appendChild( doc.createComment( u
"Plain SVG fallback, no parameters"_s ) );
2648 graphicElem.appendChild( doc.createComment( u
"Well known marker fallback"_s ) );
2654 QDomElement sizeElem = doc.createElement( u
"se:Size"_s );
2656 graphicElem.appendChild( sizeElem );
2663 if ( fillColor.isValid() )
2665 url.addQueryItem( u
"fill"_s, fillColor.name() );
2666 url.addQueryItem( u
"fill-opacity"_s,
encodeSldAlpha( fillColor.alpha() ) );
2670 url.addQueryItem( u
"fill"_s, u
"#000000"_s );
2671 url.addQueryItem( u
"fill-opacity"_s, u
"1"_s );
2673 if ( strokeColor.isValid() )
2675 url.addQueryItem( u
"outline"_s, strokeColor.name() );
2676 url.addQueryItem( u
"outline-opacity"_s,
encodeSldAlpha( strokeColor.alpha() ) );
2680 url.addQueryItem( u
"outline"_s, u
"#000000"_s );
2681 url.addQueryItem( u
"outline-opacity"_s, u
"1"_s );
2683 url.addQueryItem( u
"outline-width"_s, QString::number( strokeWidth ) );
2684 const QString params = url.toString( QUrl::FullyEncoded );
2685 if ( params.isEmpty() )
2691 return basePath +
"?" + params;
2696 QString &path, QString &mime,
2697 QColor &color,
double &size )
2702 QDomElement externalGraphicElem = element.firstChildElement( u
"ExternalGraphic"_s );
2703 if ( externalGraphicElem.isNull() )
2708 const QDomElement sizeElem = element.firstChildElement( u
"Size"_s );
2709 if ( !sizeElem.isNull() )
2712 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2721 const QString &path,
const QString &format,
int *markIndex,
2722 const QColor &color,
double size )
2730 QDomElement markElem = doc.createElement( u
"se:Mark"_s );
2731 element.appendChild( markElem );
2737 QDomElement markIndexElem = doc.createElement( u
"se:MarkIndex"_s );
2738 markIndexElem.appendChild( doc.createTextNode( QString::number( *markIndex ) ) );
2739 markElem.appendChild( markIndexElem );
2743 QDomElement fillElem = doc.createElement( u
"se:Fill"_s );
2744 fillToSld( doc, fillElem, context, Qt::SolidPattern, color );
2745 markElem.appendChild( fillElem );
2750 QDomElement sizeElem = doc.createElement( u
"se:Size"_s );
2752 element.appendChild( sizeElem );
2757 QString &path, QString &format,
int &markIndex,
2758 QColor &color,
double &size )
2766 QDomElement markElem = element.firstChildElement( u
"Mark"_s );
2767 if ( markElem.isNull() )
2772 const QDomElement markIndexElem = markElem.firstChildElement( u
"MarkIndex"_s );
2773 if ( !markIndexElem.isNull() )
2776 const int i = markIndexElem.firstChild().nodeValue().toInt( &ok );
2782 QDomElement fillElem = markElem.firstChildElement( u
"Fill"_s );
2783 Qt::BrushStyle b = Qt::SolidPattern;
2788 const QDomElement sizeElem = element.firstChildElement( u
"Size"_s );
2789 if ( !sizeElem.isNull() )
2792 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2801 const QString &name,
const QColor &color,
const QColor &strokeColor, Qt::PenStyle strokeStyle,
2802 double strokeWidth,
double size )
2805 wellKnownMarkerToSld( doc, element, name, color, strokeColor, strokeStyle, context, strokeWidth, size );
2810 QDomElement markElem = doc.createElement( u
"se:Mark"_s );
2811 element.appendChild( markElem );
2813 QDomElement wellKnownNameElem = doc.createElement( u
"se:WellKnownName"_s );
2814 wellKnownNameElem.appendChild( doc.createTextNode( name ) );
2815 markElem.appendChild( wellKnownNameElem );
2818 if ( color.isValid() )
2820 QDomElement fillElem = doc.createElement( u
"se:Fill"_s );
2821 fillToSld( doc, fillElem, context, Qt::SolidPattern, color );
2822 markElem.appendChild( fillElem );
2826 if ( strokeColor.isValid() )
2828 QDomElement strokeElem = doc.createElement( u
"se:Stroke"_s );
2829 lineToSld( doc, strokeElem, strokeStyle, strokeColor, context, strokeWidth );
2830 markElem.appendChild( strokeElem );
2836 QDomElement sizeElem = doc.createElement( u
"se:Size"_s );
2838 element.appendChild( sizeElem );
2843 QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle,
2844 double &strokeWidth,
double &size )
2850 strokeColor = QColor( 0, 0, 0 );
2854 const QDomElement markElem = element.firstChildElement( u
"Mark"_s );
2855 if ( markElem.isNull() )
2858 const QDomElement wellKnownNameElem = markElem.firstChildElement( u
"WellKnownName"_s );
2859 if ( !wellKnownNameElem.isNull() )
2861 name = wellKnownNameElem.firstChild().nodeValue();
2866 QDomElement fillElem = markElem.firstChildElement( u
"Fill"_s );
2867 Qt::BrushStyle b = Qt::SolidPattern;
2872 QDomElement strokeElem = markElem.firstChildElement( u
"Stroke"_s );
2873 lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth );
2877 const QDomElement sizeElem = element.firstChildElement( u
"Size"_s );
2878 if ( !sizeElem.isNull() )
2881 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2897 if ( !rotationFunc.isEmpty() )
2899 QDomElement rotationElem = doc.createElement( u
"se:Rotation"_s );
2901 element.appendChild( rotationElem );
2907 QDomElement rotationElem = element.firstChildElement( u
"Rotation"_s );
2908 if ( !rotationElem.isNull() )
2923 if ( !alphaFunc.isEmpty() )
2925 QDomElement opacityElem = doc.createElement( u
"se:Opacity"_s );
2927 element.appendChild( opacityElem );
2933 QDomElement opacityElem = element.firstChildElement( u
"Opacity"_s );
2934 if ( !opacityElem.isNull() )
2943 if ( offset.isNull() )
2946 QDomElement displacementElem = doc.createElement( u
"se:Displacement"_s );
2947 element.appendChild( displacementElem );
2949 QDomElement dispXElem = doc.createElement( u
"se:DisplacementX"_s );
2950 dispXElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.x(), 2 ) ) );
2952 QDomElement dispYElem = doc.createElement( u
"se:DisplacementY"_s );
2953 dispYElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.y(), 2 ) ) );
2955 displacementElem.appendChild( dispXElem );
2956 displacementElem.appendChild( dispYElem );
2963 QDomElement anchorElem = doc.createElement( u
"se:AnchorPoint"_s );
2964 element.appendChild( anchorElem );
2966 QDomElement anchorXElem = doc.createElement( u
"se:AnchorPointX"_s );
2967 anchorXElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.x() ) ) );
2969 QDomElement anchorYElem = doc.createElement( u
"se:AnchorPointY"_s );
2970 anchorYElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.y() ) ) );
2972 anchorElem.appendChild( anchorXElem );
2973 anchorElem.appendChild( anchorYElem );
2978 offset = QPointF( 0, 0 );
2980 const QDomElement displacementElem = element.firstChildElement( u
"Displacement"_s );
2981 if ( displacementElem.isNull() )
2984 const QDomElement dispXElem = displacementElem.firstChildElement( u
"DisplacementX"_s );
2985 if ( !dispXElem.isNull() )
2988 const double offsetX = dispXElem.firstChild().nodeValue().toDouble( &ok );
2990 offset.setX( offsetX );
2993 const QDomElement dispYElem = displacementElem.firstChildElement( u
"DisplacementY"_s );
2994 if ( !dispYElem.isNull() )
2997 const double offsetY = dispYElem.firstChild().nodeValue().toDouble( &ok );
2999 offset.setY( offsetY );
3006 const QString &label,
const QFont &font,
3007 const QColor &color,
double size )
3010 labelTextToSld( doc, element, label, font, context, color, size );
3015 QDomElement labelElem = doc.createElement( u
"se:Label"_s );
3016 labelElem.appendChild( doc.createTextNode( label ) );
3017 element.appendChild( labelElem );
3019 QDomElement fontElem = doc.createElement( u
"se:Font"_s );
3020 element.appendChild( fontElem );
3024 fontElem.appendChild( createSldParameterElement( doc,
"font-style",
encodeSldFontStyle( font.style() ) ) );
3025 fontElem.appendChild( createSldParameterElement( doc,
"font-weight",
encodeSldFontWeight( font.weight() ) ) );
3030 if ( color.isValid() )
3032 QDomElement fillElem = doc.createElement( u
"Fill"_s );
3033 fillToSld( doc, fillElem, context, Qt::SolidPattern, color );
3034 element.appendChild( fillElem );
3039 Qt::PenJoinStyle joinStyle,
3040 Qt::PenCapStyle capStyle,
3042 const QVector<qreal> *dashPattern )
3045 penStyle.append(
"PEN(" );
3046 penStyle.append(
"c:" );
3047 penStyle.append(
c.name() );
3048 penStyle.append(
",w:" );
3050 penStyle.append( QString::number( width * mmScaleFactor ) );
3051 penStyle.append(
"mm" );
3054 if ( dashPattern && !dashPattern->isEmpty() )
3056 penStyle.append(
",p:\"" );
3057 QVector<qreal>::const_iterator pIt = dashPattern->constBegin();
3058 for ( ; pIt != dashPattern->constEnd(); ++pIt )
3060 if ( pIt != dashPattern->constBegin() )
3062 penStyle.append(
' ' );
3064 penStyle.append( QString::number( *pIt * mapUnitScaleFactor ) );
3065 penStyle.append(
'g' );
3067 penStyle.append(
'\"' );
3071 penStyle.append(
",cap:" );
3075 penStyle.append(
'p' );
3078 penStyle.append(
'r' );
3082 penStyle.append(
'b' );
3086 penStyle.append(
",j:" );
3087 switch ( joinStyle )
3090 penStyle.append(
'b' );
3093 penStyle.append(
'r' );
3097 penStyle.append(
'm' );
3103 penStyle.append(
",dp:" );
3104 penStyle.append( QString::number( offset * mapUnitScaleFactor ) );
3105 penStyle.append(
'g' );
3108 penStyle.append(
')' );
3115 brushStyle.append(
"BRUSH(" );
3116 brushStyle.append(
"fc:" );
3117 brushStyle.append( fillColor.name() );
3118 brushStyle.append(
')' );
3130 if ( geomFunc.isEmpty() )
3133 QDomElement geometryElem = doc.createElement( u
"Geometry"_s );
3134 element.appendChild( geometryElem );
3164 QDomElement geometryElem = element.firstChildElement( u
"Geometry"_s );
3165 if ( geometryElem.isNull() )
3183 context.
pushError( QObject::tr(
"Parser error encountered when converting expression to SLD: %1 - Expression was: %2" ).arg( expr.
parserErrorString(), function ) );
3187 if ( !filterElem.isNull() )
3188 element.appendChild( filterElem );
3201 if ( function ==
"ELSE"_L1 )
3204 element.appendChild( filterElem );
3213 context.
pushError( QObject::tr(
"Parser error encountered when converting expression to SLD: %1 - Expression was: %2" ).arg( expr.
parserErrorString(), function ) );
3217 if ( !filterElem.isNull() )
3218 element.appendChild( filterElem );
3226 QDomElement elem = element;
3227 if ( element.tagName() !=
"Filter"_L1 )
3229 const QDomNodeList filterNodes = element.elementsByTagName( u
"Filter"_s );
3230 if ( !filterNodes.isEmpty() )
3232 elem = filterNodes.at( 0 ).toElement();
3236 if ( elem.isNull() )
3261 const QString &path,
const QString &format )
3265 QDomElement onlineResourceElem = doc.createElement( u
"se:OnlineResource"_s );
3266 onlineResourceElem.setAttribute( u
"xlink:type"_s, u
"simple"_s );
3267 onlineResourceElem.setAttribute( u
"xlink:href"_s, url );
3268 element.appendChild( onlineResourceElem );
3270 QDomElement formatElem = doc.createElement( u
"se:Format"_s );
3271 formatElem.appendChild( doc.createTextNode( format ) );
3272 element.appendChild( formatElem );
3279 const QDomElement onlineResourceElem = element.firstChildElement( u
"OnlineResource"_s );
3280 if ( onlineResourceElem.isNull() )
3283 path = QUrl::fromPercentEncoding( onlineResourceElem.attributeNS( u
"http://www.w3.org/1999/xlink"_s, u
"href"_s ).toUtf8() );
3285 const QDomElement formatElem = element.firstChildElement( u
"Format"_s );
3286 if ( formatElem.isNull() )
3289 format = formatElem.firstChild().nodeValue();
3296 QDomElement nodeElem = doc.createElement( u
"se:SvgParameter"_s );
3297 nodeElem.setAttribute( u
"name"_s, name );
3298 nodeElem.appendChild( doc.createTextNode( value ) );
3307 QDomElement paramElem = element.firstChildElement();
3308 while ( !paramElem.isNull() )
3310 if ( paramElem.localName() ==
"SvgParameter"_L1 || paramElem.localName() ==
"CssParameter"_L1 )
3312 const QString name = paramElem.attribute( u
"name"_s );
3313 if ( paramElem.firstChild().nodeType() == QDomNode::TextNode )
3315 value = paramElem.firstChild().nodeValue();
3319 if ( paramElem.firstChild().nodeType() == QDomNode::ElementNode &&
3320 paramElem.firstChild().localName() ==
"Literal"_L1 )
3323 value = paramElem.firstChild().firstChild().nodeValue();
3327 QgsDebugError( u
"unexpected child of %1"_s.arg( paramElem.localName() ) );
3331 if ( !name.isEmpty() && !value.isEmpty() )
3332 params[ name ] = value;
3335 paramElem = paramElem.nextSiblingElement();
3343 QDomElement nodeElem = doc.createElement( u
"se:VendorOption"_s );
3344 nodeElem.setAttribute( u
"name"_s, name );
3345 nodeElem.appendChild( doc.createTextNode( value ) );
3353 QDomElement paramElem = element.firstChildElement( u
"VendorOption"_s );
3354 while ( !paramElem.isNull() )
3356 const QString name = paramElem.attribute( u
"name"_s );
3357 const QString value = paramElem.firstChild().nodeValue();
3359 if ( !name.isEmpty() && !value.isEmpty() )
3360 params[ name ] = value;
3362 paramElem = paramElem.nextSiblingElement( u
"VendorOption"_s );
3372 if ( newSymbols.userType() == QMetaType::Type::QVariantMap )
3374 return newSymbols.toMap();
3381 QDomElement e = element.firstChildElement();
3382 while ( !e.isNull() )
3384 if ( e.tagName() ==
"prop"_L1 )
3386 const QString propKey = e.attribute( u
"k"_s );
3387 const QString propValue = e.attribute( u
"v"_s );
3388 props[propKey] = propValue;
3390 e = e.nextSiblingElement();
3407 QDomElement e = element.firstChildElement();
3409 while ( !e.isNull() )
3411 if ( e.tagName() ==
"symbol"_L1 )
3415 symbols.insert( e.attribute( u
"name"_s ), symbol.release() );
3421 e = e.nextSiblingElement();
3428 QStringList subsymbols;
3430 for ( QMap<QString, QgsSymbol *>::iterator it = symbols.begin(); it != symbols.end(); ++it )
3432 if ( it.key()[0] !=
'@' )
3436 subsymbols.append( it.key() );
3438 QStringList parts = it.key().split(
'@' );
3439 if ( parts.count() < 3 )
3441 QgsDebugError(
"found subsymbol with invalid name: " + it.key() );
3445 const QString symname = parts[1];
3446 const int symlayer = parts[2].toInt();
3448 if ( !symbols.contains( symname ) )
3450 QgsDebugError(
"subsymbol references invalid symbol: " + symname );
3458 QgsDebugError(
"subsymbol references invalid symbol layer: " + QString::number( symlayer ) );
3467 QgsDebugError(
"symbol layer refused subsymbol: " + it.key() );
3474 for (
int i = 0; i < subsymbols.count(); i++ )
3475 symbols.take( subsymbols[i] );
3482 QDomElement symbolsElem = doc.createElement( tagName );
3485 for ( QMap<QString, QgsSymbol *>::iterator its = symbols.begin(); its != symbols.end(); ++its )
3487 const QDomElement symEl =
saveSymbol( its.key(), its.value(), doc, context );
3488 symbolsElem.appendChild( symEl );
3496 qDeleteAll( symbols );
3505 std::unique_ptr< QMimeData >mimeData(
new QMimeData );
3507 QDomDocument symbolDoc;
3509 symbolDoc.appendChild( symbolElem );
3510 mimeData->setText( symbolDoc.toString() );
3513 mimeData->setColorData( symbol->
color() );
3515 return mimeData.release();
3523 const QString text = data->text();
3524 if ( !text.isEmpty() )
3529 if ( doc.setContent( text ) )
3531 elem = doc.documentElement();
3533 if ( elem.nodeName() !=
"symbol"_L1 )
3534 elem = elem.firstChildElement( u
"symbol"_s );
3545 const QString rampType = element.attribute( u
"type"_s );
3570 QDomElement rampEl = doc.createElement( u
"colorramp"_s );
3571 rampEl.setAttribute( u
"type"_s, ramp->
type() );
3572 rampEl.setAttribute( u
"name"_s, name );
3580 QVariantMap rampMap;
3582 rampMap.insert( u
"type"_s, ramp->
type() );
3583 rampMap.insert( u
"name"_s, name );
3585 const QVariantMap properties = ramp->
properties();
3587 QVariantMap propertyMap;
3588 for (
auto property = properties.constBegin(); property != properties.constEnd(); ++property )
3590 propertyMap.insert( property.key(), property.value() );
3593 rampMap.insert( u
"properties"_s, propertyMap );
3599 const QVariantMap rampMap = value.toMap();
3601 const QString rampType = rampMap.value( u
"type"_s ).toString();
3604 const QVariantMap propertyMap = rampMap.value( u
"properties"_s ).toMap();
3607 for (
auto property = propertyMap.constBegin(); property != propertyMap.constEnd(); ++property )
3609 props.insert( property.key(), property.value().toString() );
3631 if ( !color.isValid() )
3638 return color.name();
3643 QList<QColor> colors;
3646 const thread_local QRegularExpression sepCommaSpaceRegExp(
"(,|\\s)" );
3647 QStringList components = colorStr.simplified().split( sepCommaSpaceRegExp );
3648 QStringList::iterator it = components.begin();
3649 for ( ; it != components.end(); ++it )
3651 const QColor result =
parseColor( *it,
true );
3652 if ( result.isValid() )
3657 if ( colors.length() > 0 )
3663 const thread_local QRegularExpression sepCommaRegExp(
"(,|\n)" );
3664 components = colorStr.split( sepCommaRegExp );
3665 it = components.begin();
3666 for ( ; it != components.end(); ++it )
3668 const QColor result =
parseColor( *it,
true );
3669 if ( result.isValid() )
3674 if ( colors.length() > 0 )
3680 components = colorStr.simplified().split( QString(
' ' ) );
3681 it = components.begin();
3682 for ( ; it != components.end(); ++it )
3684 const QColor result =
parseColor( *it,
true );
3685 if ( result.isValid() )
3690 if ( colors.length() > 0 )
3696 components = colorStr.split(
'\n' );
3697 it = components.begin();
3698 for ( ; it != components.end(); ++it )
3700 const QColor result =
parseColor( *it,
true );
3701 if ( result.isValid() )
3714 QMimeData *mimeData =
new QMimeData;
3715 mimeData->setColorData( QVariant( color ) );
3716 mimeData->setText( color.name() );
3726 if ( mimeData->hasColor() )
3728 QColor mimeColor = mimeData->colorData().value<QColor>();
3729 if ( mimeColor.isValid() )
3737 if ( mimeData->hasText() )
3741 if ( textColor.isValid() )
3759 if ( data->hasFormat( u
"text/xml"_s ) )
3762 const QByteArray encodedData = data->data( u
"text/xml"_s );
3763 QDomDocument xmlDoc;
3764 xmlDoc.setContent( encodedData );
3766 const QDomElement dragDataElem = xmlDoc.documentElement();
3767 if ( dragDataElem.tagName() ==
"ColorSchemeModelDragData"_L1 )
3769 const QDomNodeList nodeList = dragDataElem.childNodes();
3770 const int nChildNodes = nodeList.size();
3771 QDomElement currentElem;
3773 for (
int i = 0; i < nChildNodes; ++i )
3775 currentElem = nodeList.at( i ).toElement();
3776 if ( currentElem.isNull() )
3781 QPair< QColor, QString> namedColor;
3783 namedColor.second = currentElem.attribute( u
"label"_s, QString() );
3785 mimeColors << namedColor;
3790 if ( mimeColors.length() == 0 && data->hasFormat( u
"application/x-colorobject-list"_s ) )
3793 const QByteArray encodedData = data->data( u
"application/x-colorobject-list"_s );
3794 QDomDocument xmlDoc;
3795 xmlDoc.setContent( encodedData );
3797 const QDomNodeList colorsNodes = xmlDoc.elementsByTagName( u
"colors"_s );
3798 if ( colorsNodes.length() > 0 )
3800 const QDomElement colorsElem = colorsNodes.at( 0 ).toElement();
3801 const QDomNodeList colorNodeList = colorsElem.childNodes();
3802 const int nChildNodes = colorNodeList.size();
3803 QDomElement currentElem;
3805 for (
int i = 0; i < nChildNodes; ++i )
3808 currentElem = colorNodeList.at( i ).toElement();
3809 if ( currentElem.isNull() )
3814 const QDomNodeList colorNodes = currentElem.elementsByTagName( u
"color"_s );
3815 const QDomNodeList nameNodes = currentElem.elementsByTagName( u
"name"_s );
3817 if ( colorNodes.length() > 0 )
3819 const QDomElement colorElem = colorNodes.at( 0 ).toElement();
3821 const QStringList colorParts = colorElem.text().simplified().split(
' ' );
3822 if ( colorParts.length() < 3 )
3827 const int red = colorParts.at( 0 ).toDouble() * 255;
3828 const int green = colorParts.at( 1 ).toDouble() * 255;
3829 const int blue = colorParts.at( 2 ).toDouble() * 255;
3830 QPair< QColor, QString> namedColor;
3831 namedColor.first = QColor( red, green, blue );
3832 if ( nameNodes.length() > 0 )
3834 const QDomElement nameElem = nameNodes.at( 0 ).toElement();
3835 namedColor.second = nameElem.text();
3837 mimeColors << namedColor;
3843 if ( mimeColors.length() == 0 && data->hasText() )
3847 QList< QColor >::iterator it = parsedColors.begin();
3848 for ( ; it != parsedColors.end(); ++it )
3850 mimeColors << qMakePair( *it, QString() );
3854 if ( mimeColors.length() == 0 && data->hasColor() )
3857 const QColor mimeColor = data->colorData().value<QColor>();
3858 if ( mimeColor.isValid() )
3860 mimeColors << qMakePair( mimeColor, QString() );
3870 QMimeData *mimeData =
new QMimeData();
3871 QDomDocument xmlDoc;
3872 QDomElement xmlRootElement = xmlDoc.createElement( u
"ColorSchemeModelDragData"_s );
3873 xmlDoc.appendChild( xmlRootElement );
3875 QgsNamedColorList::const_iterator colorIt = colorList.constBegin();
3876 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3878 QDomElement namedColor = xmlDoc.createElement( u
"NamedColor"_s );
3880 namedColor.setAttribute( u
"label"_s, ( *colorIt ).second );
3881 xmlRootElement.appendChild( namedColor );
3883 mimeData->setData( u
"text/xml"_s, xmlDoc.toByteArray() );
3891 colorIt = colorList.constBegin();
3892 QStringList colorListString;
3893 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3895 colorListString << ( *colorIt ).first.name();
3897 mimeData->setText( colorListString.join( QLatin1Char(
'\n' ) ) );
3900 if ( colorList.length() > 0 )
3902 mimeData->setColorData( QVariant( colorList.at( 0 ).first ) );
3910 if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3915 QTextStream stream( &file );
3917 stream <<
"GIMP Palette" << Qt::endl;
3918 if ( paletteName.isEmpty() )
3920 stream <<
"Name: QGIS Palette" << Qt::endl;
3924 stream <<
"Name: " << paletteName << Qt::endl;
3926 stream <<
"Columns: 4" << Qt::endl;
3927 stream <<
'#' << Qt::endl;
3929 for ( QgsNamedColorList::ConstIterator colorIt = colors.constBegin(); colorIt != colors.constEnd(); ++colorIt )
3931 const QColor color = ( *colorIt ).first;
3932 if ( !color.isValid() )
3936 stream << u
"%1 %2 %3"_s.arg( color.red(), 3 ).arg( color.green(), 3 ).arg( color.blue(), 3 );
3937 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << Qt::endl;
3948 if ( !file.open( QIODevice::ReadOnly ) )
3951 return importedColors;
3954 QTextStream in( &file );
3956 QString line = in.readLine();
3957 if ( !line.startsWith(
"GIMP Palette"_L1 ) )
3960 return importedColors;
3964 while ( !in.atEnd() && !line.startsWith(
"Name:"_L1 ) && !line.startsWith(
'#' ) )
3966 line = in.readLine();
3968 if ( line.startsWith(
"Name:"_L1 ) )
3970 const thread_local QRegularExpression nameRx(
"Name:\\s*(\\S.*)$" );
3971 const QRegularExpressionMatch match = nameRx.match( line );
3972 if ( match.hasMatch() )
3974 name = match.captured( 1 );
3979 while ( !in.atEnd() && !line.startsWith(
'#' ) )
3981 line = in.readLine();
3986 return importedColors;
3990 const thread_local QRegularExpression rx(
"^\\s*(\\d+)\\s+(\\d+)\\s+(\\d+)(\\s.*)?$" );
3991 while ( !in.atEnd() )
3993 line = in.readLine();
3994 const QRegularExpressionMatch match = rx.match( line );
3995 if ( !match.hasMatch() )
3999 const int red = match.captured( 1 ).toInt();
4000 const int green = match.captured( 2 ).toInt();
4001 const int blue = match.captured( 3 ).toInt();
4002 const QColor color = QColor( red, green, blue );
4003 if ( !color.isValid() )
4010 if ( rx.captureCount() > 3 )
4012 label = match.captured( 4 ).simplified();
4019 importedColors << qMakePair( color, label );
4024 return importedColors;
4037 const thread_local QRegularExpression hexColorAlphaRx(
"^\\s*#?([0-9a-fA-F]{6})([0-9a-fA-F]{2})\\s*$" );
4038 QRegularExpressionMatch match = hexColorAlphaRx.match( colorStr );
4041 if ( !match.hasMatch() && QColor::isValidColor( colorStr ) )
4044 parsedColor.setNamedColor( colorStr );
4045 if ( parsedColor.isValid() )
4047 containsAlpha =
false;
4053 if ( match.hasMatch() )
4055 const QString hexColor = match.captured( 1 );
4056 parsedColor.setNamedColor( u
"#"_s + hexColor );
4058 const int alphaHex = match.captured( 2 ).toInt( &alphaOk, 16 );
4060 if ( parsedColor.isValid() && alphaOk )
4062 parsedColor.setAlpha( alphaHex );
4063 containsAlpha =
true;
4071 const thread_local QRegularExpression hexColorRx2(
"^\\s*(?:[0-9a-fA-F]{3}){1,2}\\s*$" );
4072 if ( colorStr.indexOf( hexColorRx2 ) != -1 )
4075 parsedColor.setNamedColor( u
"#"_s + colorStr );
4076 if ( parsedColor.isValid() )
4078 containsAlpha =
false;
4085 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*$" );
4086 match = rgbFormatRx.match( colorStr );
4087 if ( match.hasMatch() )
4092 const int r = match.captured( 1 ).toInt( &rOk );
4093 const int g = match.captured( 2 ).toInt( &gOk );
4094 const int b = match.captured( 3 ).toInt( &bOk );
4096 if ( !rOk || !gOk || !bOk )
4098 const float rFloat = match.captured( 1 ).toFloat();
4099 const float gFloat = match.captured( 2 ).toFloat();
4100 const float bFloat = match.captured( 3 ).toFloat();
4101 parsedColor.setRgbF( rFloat / 255.0, gFloat / 255.0, bFloat / 255.0 );
4105 parsedColor.setRgb( r, g, b );
4108 if ( parsedColor.isValid() )
4110 containsAlpha =
false;
4116 const thread_local QRegularExpression hslFormatRx(
"^\\s*hsl\\(?\\s*(\\d+(?:\\.\\d*)?)\\s*,\\s*(\\d+(?:\\.\\d*)?)\\s*%\\s*,\\s*(\\d+(?:\\.\\d*)?)\\s*%\\s*\\)?\\s*;?\\s*$" );
4117 match = hslFormatRx.match( colorStr );
4118 if ( match.hasMatch() )
4123 const int h = match.captured( 1 ).toInt( &hOk );
4124 const int s = match.captured( 2 ).toInt( &sOk );
4125 const int l = match.captured( 3 ).toInt( &lOk );
4127 if ( !hOk || !sOk || !lOk )
4129 const float hFloat = match.captured( 1 ).toFloat();
4130 const float sFloat = match.captured( 2 ).toFloat();
4131 const float lFloat = match.captured( 3 ).toFloat();
4132 parsedColor.setHslF( hFloat / 360.0, sFloat / 100.0, lFloat / 100.0 );
4136 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0 );
4138 if ( parsedColor.isValid() )
4140 containsAlpha =
false;
4146 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*$" );
4147 match = rgbPercentFormatRx.match( colorStr );
4148 if ( match.hasMatch() )
4150 const double r = match.captured( 1 ).toDouble() / 100;
4151 const double g = match.captured( 2 ).toDouble() / 100;
4152 const double b = match.captured( 3 ).toDouble() / 100;
4153 parsedColor.setRgbF( r, g, b );
4154 if ( parsedColor.isValid() )
4156 containsAlpha =
false;
4162 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*$" );
4163 match = rgbaFormatRx.match( colorStr );
4164 if ( match.hasMatch() )
4169 const int r = match.captured( 1 ).toInt( &rOk );
4170 const int g = match.captured( 2 ).toInt( &gOk );
4171 const int b = match.captured( 3 ).toInt( &bOk );
4172 const double aDouble = match.captured( 4 ).toDouble();
4174 if ( !rOk || !gOk || !bOk )
4176 const float rFloat = match.captured( 1 ).toFloat();
4177 const float gFloat = match.captured( 2 ).toFloat();
4178 const float bFloat = match.captured( 3 ).toFloat();
4179 parsedColor.setRgbF( rFloat / 255.0, gFloat / 255.0, bFloat / 255.0, aDouble );
4183 const int a =
static_cast< int >( std::round( match.captured( 4 ).toDouble() * 255.0 ) );
4184 parsedColor.setRgb( r, g, b, a );
4186 if ( parsedColor.isValid() )
4188 containsAlpha =
true;
4194 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*$" );
4195 match = rgbaPercentFormatRx.match( colorStr );
4196 if ( match.hasMatch() )
4198 const double r = match.captured( 1 ).toDouble() / 100;
4199 const double g = match.captured( 2 ).toDouble() / 100;
4200 const double b = match.captured( 3 ).toDouble() / 100;
4201 const double a = match.captured( 4 ).toDouble();
4202 parsedColor.setRgbF( r, g, b, a );
4203 if ( parsedColor.isValid() )
4205 containsAlpha =
true;
4211 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*$" );
4212 match = hslaPercentFormatRx.match( colorStr );
4213 if ( match.hasMatch() )
4218 const int h = match.captured( 1 ).toInt( &hOk );
4219 const int s = match.captured( 2 ).toInt( &sOk );
4220 const int l = match.captured( 3 ).toInt( &lOk );
4221 const double aDouble = match.captured( 4 ).toDouble();
4223 if ( !hOk || !sOk || !lOk )
4225 const float hFloat = match.captured( 1 ).toFloat();
4226 const float sFloat = match.captured( 2 ).toFloat();
4227 const float lFloat = match.captured( 3 ).toFloat();
4228 parsedColor.setHslF( hFloat / 360.0, sFloat / 100.0, lFloat / 100.0, aDouble );
4232 const int a = std::round( aDouble * 255.0 );
4233 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0, a );
4236 if ( parsedColor.isValid() )
4238 containsAlpha =
true;
4255 const QImage::Format format = image->format();
4256 if ( format != QImage::Format_ARGB32_Premultiplied && format != QImage::Format_ARGB32 )
4263 for (
int heightIndex = 0; heightIndex < image->height(); ++heightIndex )
4265 QRgb *scanLine =
reinterpret_cast< QRgb *
>( image->scanLine( heightIndex ) );
4266 for (
int widthIndex = 0; widthIndex < image->width(); ++widthIndex )
4268 myRgb = scanLine[widthIndex];
4269 if ( format == QImage::Format_ARGB32_Premultiplied )
4270 scanLine[widthIndex] = qRgba( opacity * qRed( myRgb ), opacity * qGreen( myRgb ), opacity * qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4272 scanLine[widthIndex] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4280 const int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
4281 const int alpha = ( radius < 1 ) ? 16 : ( radius > 17 ) ? 1 : tab[radius - 1];
4283 if ( image.format() != QImage::Format_ARGB32_Premultiplied
4284 && image.format() != QImage::Format_RGB32 )
4286 image = image.convertToFormat( QImage::Format_ARGB32_Premultiplied );
4289 const int r1 = rect.top();
4290 const int r2 = rect.bottom();
4291 const int c1 = rect.left();
4292 const int c2 = rect.right();
4294 const int bpl = image.bytesPerLine();
4302 i1 = i2 = ( QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3 );
4304 for (
int col = c1; col <= c2; col++ )
4306 p = image.scanLine( r1 ) + col * 4;
4307 for (
int i = i1; i <= i2; i++ )
4308 rgba[i] = p[i] << 4;
4311 for (
int j = r1; j < r2; j++, p += bpl )
4312 for (
int i = i1; i <= i2; i++ )
4313 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4316 for (
int row = r1; row <= r2; row++ )
4318 p = image.scanLine( row ) + c1 * 4;
4319 for (
int i = i1; i <= i2; i++ )
4320 rgba[i] = p[i] << 4;
4323 for (
int j = c1; j < c2; j++, p += 4 )
4324 for (
int i = i1; i <= i2; i++ )
4325 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4328 for (
int col = c1; col <= c2; col++ )
4330 p = image.scanLine( r2 ) + col * 4;
4331 for (
int i = i1; i <= i2; i++ )
4332 rgba[i] = p[i] << 4;
4335 for (
int j = r1; j < r2; j++, p -= bpl )
4336 for (
int i = i1; i <= i2; i++ )
4337 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4340 for (
int row = r1; row <= r2; row++ )
4342 p = image.scanLine( row ) + c2 * 4;
4343 for (
int i = i1; i <= i2; i++ )
4344 rgba[i] = p[i] << 4;
4347 for (
int j = c1; j < c2; j++, p -= 4 )
4348 for (
int i = i1; i <= i2; i++ )
4349 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4355 if ( alpha != 255 && alpha > 0 )
4359 const double alphaFactor = alpha / 255.;
4360 int r = 0, g = 0, b = 0;
4361 rgb.getRgb( &r, &g, &b );
4366 rgb.setRgb( r, g, b, alpha );
4368 else if ( alpha == 0 )
4370 rgb.setRgb( 0, 0, 0, 0 );
4379 if ( !simpleFill || !simpleLine )
4403 if ( simpleLine->
offset() )
4421 if ( order == Qt::AscendingOrder )
4435 const double dx = directionPoint.x() - startPoint.x();
4436 const double dy = directionPoint.y() - startPoint.y();
4437 const double length = std::sqrt( dx * dx + dy * dy );
4438 const double scaleFactor = distance / length;
4439 return QPointF( startPoint.x() + dx * scaleFactor, startPoint.y() + dy * scaleFactor );
4449 for (
int i = 0; i < svgPaths.size(); i++ )
4451 const QDir dir( svgPaths[i] );
4452 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4453 for (
const QString &item : svgSubPaths )
4455 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4458 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4459 for (
const QString &item : svgFiles )
4462 list.append( dir.path() +
'/' + item );
4474 QStringList svgPaths;
4475 svgPaths.append( directory );
4477 for (
int i = 0; i < svgPaths.size(); i++ )
4479 const QDir dir( svgPaths[i] );
4480 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4481 for (
const QString &item : svgSubPaths )
4483 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4486 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4487 for (
const QString &item : svgFiles )
4489 list.append( dir.path() +
'/' + item );
4501 if ( n.startsWith(
"base64:"_L1 ) )
4505 if ( QFileInfo::exists( n ) )
4506 return QFileInfo( n ).canonicalFilePath();
4510 if ( name.contains(
"://"_L1 ) )
4512 const QUrl url( name );
4513 if ( url.isValid() && !url.scheme().isEmpty() )
4515 if ( url.scheme().compare(
"file"_L1, Qt::CaseInsensitive ) == 0 )
4518 name = url.toLocalFile();
4519 if ( QFile( name ).exists() )
4521 return QFileInfo( name ).canonicalFilePath();
4535 for (
int i = 0; i < svgPaths.size(); i++ )
4537 QString svgPath = svgPaths[i];
4538 if ( svgPath.endsWith( QChar(
'/' ) ) )
4549 const QString myLocalPath = svgPath + QDir::separator() + name;
4552 if ( QFile( myLocalPath ).exists() )
4555 return QFileInfo( myLocalPath ).canonicalFilePath();
4559 return pathResolver.
readPath( name );
4567 if ( p.startsWith(
"base64:"_L1 ) )
4570 if ( !QFileInfo::exists( p ) )
4573 QString path = QFileInfo( p ).canonicalFilePath();
4577 bool isInSvgPaths =
false;
4578 for (
int i = 0; i < svgPaths.size(); i++ )
4580 const QString dir = QFileInfo( svgPaths[i] ).canonicalFilePath();
4582 if ( !dir.isEmpty() && path.startsWith( dir ) )
4584 path = path.mid( dir.size() + 1 );
4585 isInSvgPaths =
true;
4598 const double *srcX = line->
xData();
4599 const double *srcY = line->
yData();
4601 QPolygonF thisRes( count );
4602 QPointF *dest = thisRes.data();
4603 for (
int i = 0; i < count; ++i )
4605 *dest++ = QPointF( *srcX++, *srcY++ );
4618 const std::unique_ptr< QgsLineString > straightened( curve->
curveToLine() );
4642 points << QPointF( ( *it ).x(), ( *it ).y() );
4646 points << QPointF( 0, 0 );
4648 return QList< QList<QPolygonF> >() << ( QList< QPolygonF >() << points );
4653 QList< QList<QPolygonF> > res;
4666 QList< QList<QPolygonF> > res;
4670 QList<QPolygonF> thisPart;
4689 return QList< QList<QPolygonF> >();
4692 return QList< QList<QPolygonF> >();
4699 double cx = 0, cy = 0;
4700 double area, sum = 0;
4701 for (
int i = points.count() - 1, j = 0; j < points.count(); i = j++ )
4703 const QPointF &p1 = points[i];
4704 const QPointF &p2 = points[j];
4705 area = p1.x() * p2.y() - p1.y() * p2.x();
4707 cx += ( p1.x() + p2.x() ) * area;
4708 cy += ( p1.y() + p2.y() ) * area;
4715 if ( points.count() >= 2 )
4716 return QPointF( ( points[0].x() + points[1].x() ) / 2, ( points[0].y() + points[1].y() ) / 2 );
4717 else if ( points.count() == 1 )
4725 return QPointF( cx, cy );
4732 if ( ( rings && rings->count() > 0 ) || !
pointInPolygon( points, centroid ) )
4734 unsigned int i, pointCount = points.count();
4736 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( points[i].x(), points[i].y() );
4742 for (
auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
4744 pointCount = ( *ringIt ).count();
4746 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( ( *ringIt )[i].x(), ( *ringIt )[i].y() );
4752 if ( !pointOnSurfaceGeom.
isNull() )
4755 centroid.
setX( point.
x() );
4756 centroid.setY( point.
y() );
4761 return QPointF( centroid.x(), centroid.y() );
4766 bool inside =
false;
4768 const double x = point.x();
4769 const double y = point.y();
4771 for (
int i = 0, j = points.count() - 1; i < points.count(); i++ )
4773 const QPointF &p1 = points[i];
4774 const QPointF &p2 = points[j];
4779 if ( ( p1.y() < y && p2.y() >= y ) || ( p2.y() < y && p1.y() >= y ) )
4781 if ( p1.x() + ( y - p1.y() ) / ( p2.y() - p1.y() ) * ( p2.x() - p1.x() ) <= x )
4792 if ( polyline.size() < 2 )
4795 double totalLength = 0;
4796 auto it = polyline.begin();
4798 for ( ; it != polyline.end(); ++it )
4800 const QPointF p2 = *it;
4801 const double segmentLength = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4802 totalLength += segmentLength;
4810 if ( polyline.size() < 2 )
4813 double totalLength = 0;
4814 auto it = polyline.begin();
4816 std::vector< double > segmentLengths( polyline.size() - 1 );
4817 auto segmentLengthIt = segmentLengths.begin();
4818 for ( ; it != polyline.end(); ++it )
4820 const QPointF p2 = *it;
4821 *segmentLengthIt = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4822 totalLength += *segmentLengthIt;
4828 if ( startOffset >= 0 && totalLength <= startOffset )
4830 if ( endOffset < 0 && totalLength <= -endOffset )
4833 const double startDistance = startOffset < 0 ? totalLength + startOffset : startOffset;
4834 const double endDistance = endOffset <= 0 ? totalLength + endOffset : endOffset;
4835 QPolygonF substringPoints;
4836 substringPoints.reserve( polyline.size() );
4838 it = polyline.begin();
4839 segmentLengthIt = segmentLengths.begin();
4842 bool foundStart =
false;
4843 if (
qgsDoubleNear( startDistance, 0.0 ) || startDistance < 0 )
4845 substringPoints << p1;
4849 double distanceTraversed = 0;
4850 for ( ; it != polyline.end(); ++it )
4852 const QPointF p2 = *it;
4853 if ( distanceTraversed < startDistance && distanceTraversed + *segmentLengthIt > startDistance )
4856 const double distanceToStart = startDistance - distanceTraversed;
4857 double startX, startY;
4859 substringPoints << QPointF( startX, startY );
4862 if ( foundStart && ( distanceTraversed + *segmentLengthIt > endDistance ) )
4865 const double distanceToEnd = endDistance - distanceTraversed;
4868 if ( substringPoints.last() != QPointF( endX, endY ) )
4869 substringPoints << QPointF( endX, endY );
4871 else if ( foundStart )
4873 if ( substringPoints.last() != QPointF( p2.x(), p2.y() ) )
4874 substringPoints << QPointF( p2.x(), p2.y() );
4877 distanceTraversed += *segmentLengthIt;
4878 if ( distanceTraversed > endDistance )
4885 if ( ( substringPoints.size() < 2 ) || ( substringPoints.size() == 2 && substringPoints.at( 0 ) == substringPoints.at( 1 ) ) )
4888 return substringPoints;
4893 double vertexAngle = M_PI - ( std::atan2( p3.y() - p2.y(), p3.x() - p2.x() ) - std::atan2( p2.y() - p1.y(), p2.x() - p1.x() ) );
4897 return vertexAngle < M_PI * 135.0 / 180.0 || vertexAngle > M_PI * 225.0 / 180.0;
4902 target.reserve( target.size() + line.size() );
4903 for (
const QPointF &pt : line )
4905 if ( !target.empty() && target.last() == pt )
4914 if ( fieldOrExpression.isEmpty() )
4917 auto expr = std::make_unique< QgsExpression >( fieldOrExpression );
4918 if ( !expr->hasParserError() )
4923 Q_ASSERT( !expr->hasParserError() );
4948 QList<double> breaks;
4951 breaks.append( maximum );
4955 const int minimumCount =
static_cast< int >( classes ) / 3;
4956 const double shrink = 0.75;
4957 const double highBias = 1.5;
4958 const double adjustBias = 0.5 + 1.5 * highBias;
4959 const int divisions = classes;
4960 const double h = highBias;
4963 const double dx = maximum - minimum;
4973 cell = std::max( std::fabs( minimum ), std::fabs( maximum ) );
4974 if ( adjustBias >= 1.5 * h + 0.5 )
4976 U = 1 + ( 1.0 / ( 1 + h ) );
4980 U = 1 + ( 1.5 / ( 1 + adjustBias ) );
4982 small = dx < ( cell * U * std::max( 1, divisions ) * 1e-07 * 3.0 );
4989 cell = 9 + cell / 10;
4990 cell = cell * shrink;
4992 if ( minimumCount > 1 )
4994 cell = cell / minimumCount;
5000 if ( divisions > 1 )
5002 cell = cell / divisions;
5005 if ( cell < 20 * 1e-07 )
5010 const double base = std::pow( 10.0, std::floor( std::log10( cell ) ) );
5012 if ( ( 2 * base ) - cell < h * ( cell - unit ) )
5015 if ( ( 5 * base ) - cell < adjustBias * ( cell - unit ) )
5018 if ( ( 10.0 * base ) - cell < h * ( cell - unit ) )
5025 int start = std::floor( minimum / unit + 1e-07 );
5026 int end = std::ceil( maximum / unit - 1e-07 );
5029 while ( start * unit > minimum + ( 1e-07 * unit ) )
5033 while ( end * unit < maximum - ( 1e-07 * unit ) )
5041 int k = std::floor( 0.5 + end - start );
5042 if ( k < minimumCount )
5044 k = minimumCount - k;
5048 start = start - k / 2 + k % 2;
5052 start = start - k / 2;
5053 end = end + k / 2 + k % 2;
5056 const double minimumBreak = start * unit;
5058 const int count = end - start;
5060 breaks.reserve( count );
5061 for (
int i = 1; i < count + 1; i++ )
5063 breaks.append( minimumBreak + i * unit );
5066 if ( breaks.isEmpty() )
5069 if ( breaks.first() < minimum )
5071 breaks[0] = minimum;
5073 if ( breaks.last() > maximum )
5075 breaks[breaks.count() - 1] = maximum;
5080 if ( minimum < 0.0 && maximum > 0.0 )
5082 QList<double> breaksMinusZero;
5083 for (
int i = 0; i < breaks.count(); i++ )
5085 breaksMinusZero.append( breaks[i] - 0.0 );
5088 for (
int i = 1; i < breaks.count(); i++ )
5090 if ( std::abs( breaksMinusZero[i] ) < std::abs( breaksMinusZero[i - 1] ) )
5093 breaks[posOfMin] = 0.0;
5102 bool roundToUnit =
false;
5105 if ( props.contains( u
"uomScale"_s ) )
5108 scale = props.value( u
"uomScale"_s ).toDouble( &ok );
5117 if ( props.value( u
"uom"_s ) ==
"http://www.opengeospatial.org/se/units/metre"_L1 )
5142 scale = 1 / 0.28 * 25.4;
5166 double rescaled = size * scale;
5171 rescaled = std::round( rescaled );
5178 const double x =
rescaleUom( point.x(), unit, props );
5179 const double y =
rescaleUom( point.y(), unit, props );
5180 return QPointF( x, y );
5185 QVector<qreal> result;
5186 QVector<qreal>::const_iterator it = array.constBegin();
5187 for ( ; it != array.constEnd(); ++it )
5189 result.append(
rescaleUom( *it, unit, props ) );
5196 if ( !props.value( u
"scaleMinDenom"_s, QString() ).toString().isEmpty() )
5198 QDomElement scaleMinDenomElem = doc.createElement( u
"se:MinScaleDenominator"_s );
5199 scaleMinDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( u
"scaleMinDenom"_s ).toString().toDouble() ) ) );
5200 ruleElem.appendChild( scaleMinDenomElem );
5203 if ( !props.value( u
"scaleMaxDenom"_s, QString() ).toString().isEmpty() )
5205 QDomElement scaleMaxDenomElem = doc.createElement( u
"se:MaxScaleDenominator"_s );
5206 scaleMaxDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( u
"scaleMaxDenom"_s ).toString().toDouble() ) ) );
5207 ruleElem.appendChild( scaleMaxDenomElem );
5216 const double parentScaleMinDenom = props.value( u
"scaleMinDenom"_s, u
"0"_s ).toString().toDouble( &ok );
5217 if ( !ok || parentScaleMinDenom <= 0 )
5218 props[ u
"scaleMinDenom"_s] = QString::number( mScaleMinDenom );
5220 props[ u
"scaleMinDenom"_s] = QString::number( std::max( parentScaleMinDenom, mScaleMinDenom ) );
5226 const double parentScaleMaxDenom = props.value( u
"scaleMaxDenom"_s, u
"0"_s ).toString().toDouble( &ok );
5227 if ( !ok || parentScaleMaxDenom <= 0 )
5228 props[ u
"scaleMaxDenom"_s] = QString::number( mScaleMaxDenom );
5230 props[ u
"scaleMaxDenom"_s] = QString::number( std::min( parentScaleMaxDenom, mScaleMaxDenom ) );
5238 if ( uom ==
"http://www.opengeospatial.org/se/units/metre"_L1 )
5240 scale = 1.0 / 0.00028;
5242 else if ( uom ==
"http://www.opengeospatial.org/se/units/foot"_L1 )
5244 scale = 304.8 / 0.28;
5251 return size * scale;
5260 SymbolLayerVisitor(
const QSet<QgsSymbolLayerId> &layerIds )
5261 : mSymbolLayerIds( layerIds )
5274 void visitSymbol(
const QgsSymbol *symbol,
const QString &identifier, QVector<int> rootPath )
5278 QVector<int> indexPath = rootPath;
5279 indexPath.append( idx );
5282 if ( mSymbolLayerIds.contains(
QgsSymbolLayerId( mCurrentRuleKey + identifier, indexPath ) ) )
5284 mSymbolLayers.insert( sl );
5290 visitSymbol( subSymbol, identifier, indexPath );
5299 if ( symbolEntity->symbol() )
5301 visitSymbol( symbolEntity->symbol(), leaf.
identifier, {} );
5307 QString mCurrentRuleKey;
5308 const QSet<QgsSymbolLayerId> &mSymbolLayerIds;
5309 QSet<const QgsSymbolLayer *> mSymbolLayers;
5313 SymbolLayerVisitor visitor( symbolLayerIds );
5314 renderer->
accept( &visitor );
5315 return visitor.mSymbolLayers;
5323 SymbolRefreshRateVisitor()
5335 void visitSymbol(
const QgsSymbol *symbol )
5352 if ( refreshRate == -1 || ( animatedMarker->frameRate() > refreshRate ) )
5353 refreshRate = animatedMarker->frameRate();
5357 visitSymbol( subSymbol );
5365 if (
QgsSymbol *symbol = qgis::down_cast<const QgsStyleSymbolEntity *>( leaf.
entity )->symbol() )
5367 visitSymbol( symbol );
5373 double refreshRate = -1;
5376 SymbolRefreshRateVisitor visitor;
5377 renderer->
accept( &visitor );
5378 return visitor.refreshRate;
5383 if ( !s || !context )
5409 size = markerSymbol->
size( *context );
5411 else if ( lineSymbol )
5413 size = lineSymbol->
width( *context );
5425 if ( minSize > 0 && size < minSize )
5429 else if ( maxSize > 0 && size > maxSize )
5441 std::unique_ptr< QgsMarkerSymbol > ms( markerSymbol->
clone() );
5442 ms->setSize( size );
5448 else if ( lineSymbol )
5450 std::unique_ptr< QgsLineSymbol > ls( lineSymbol->
clone() );
5451 ls->setWidth( size );
5463 QMap<QString, QgsProperty>::const_iterator paramIt = propertiesMap.constBegin();
5464 for ( ; paramIt != propertiesMap.constEnd(); ++paramIt )
5466 properties.insert( paramIt.key(), paramIt.value().valueAsString( context ) );
5474 angleRad = std::fmod( angleRad, M_PI * 2 );
5478 angleRad += M_PI * 2;
5482 struct rationalTangent
5494 static const QList<rationalTangent> __rationalTangents
5496 { 1, 57, 0.01754206006 },
5497 { 3, 86, 0.03486958155 },
5498 { 1, 19, 0.05258306161 },
5499 { 3, 43, 0.06965457373 },
5500 { 7, 80, 0.08727771295 },
5501 { 2, 19, 0.1048769387 },
5502 { 7, 57, 0.1221951707 },
5503 { 9, 64, 0.1397088743 },
5504 { 13, 82, 0.157228051 },
5505 { 3, 17, 0.174672199 },
5506 { 7, 36, 0.1920480172 },
5507 { 17, 80, 0.209385393 },
5508 { 3, 13, 0.2267988481 },
5509 { 1, 4, 0.2449786631 },
5510 { 26, 97, 0.2618852647 },
5511 { 27, 94, 0.2797041525 },
5512 { 26, 85, 0.2968446734 },
5513 { 13, 40, 0.3142318991 },
5514 { 21, 61, 0.3315541619 },
5515 { 4, 11, 0.3487710036 },
5516 { 38, 99, 0.3664967859 },
5517 { 40, 99, 0.383984624 },
5518 { 31, 73, 0.4015805401 },
5519 { 41, 92, 0.4192323938 },
5520 { 7, 15, 0.4366271598 },
5521 { 20, 41, 0.4538440015 },
5522 { 27, 53, 0.4711662643 },
5523 { 42, 79, 0.4886424026 },
5524 { 51, 92, 0.5061751436 },
5525 { 56, 97, 0.5235757641 },
5526 { 3, 5, 0.5404195003 },
5527 { 5, 8, 0.5585993153 },
5528 { 50, 77, 0.5759185996 },
5529 { 29, 43, 0.5933501462 },
5530 { 7, 10, 0.6107259644 },
5531 { 69, 95, 0.6281701124 },
5532 { 52, 69, 0.6458159195 },
5533 { 25, 32, 0.6632029927 },
5534 { 17, 21, 0.6805212247 },
5535 { 73, 87, 0.6981204504 },
5536 { 73, 84, 0.7154487784 },
5537 { 9, 10, 0.7328151018 },
5538 { 83, 89, 0.7505285818 },
5539 { 28, 29, 0.7678561033 },
5540 { 1, 1, 0.7853981634 },
5541 { 29, 28, 0.8029402235 },
5542 { 89, 83, 0.820267745 },
5543 { 10, 9, 0.837981225 },
5544 { 107, 93, 0.855284165 },
5545 { 87, 73, 0.8726758763 },
5546 { 121, 98, 0.8900374031 },
5547 { 32, 25, 0.9075933341 },
5548 { 69, 52, 0.9249804073 },
5549 { 128, 93, 0.9424647244 },
5550 { 10, 7, 0.9600703624 },
5551 { 43, 29, 0.9774461806 },
5552 { 77, 50, 0.9948777272 },
5553 { 8, 5, 1.012197011 },
5554 { 163, 98, 1.029475114 },
5555 { 168, 97, 1.047174539 },
5556 { 175, 97, 1.064668696 },
5557 { 126, 67, 1.082075603 },
5558 { 157, 80, 1.099534652 },
5559 { 203, 99, 1.117049384 },
5560 { 193, 90, 1.134452855 },
5561 { 146, 65, 1.151936673 },
5562 { 139, 59, 1.169382787 },
5563 { 99, 40, 1.186811703 },
5564 { 211, 81, 1.204257817 },
5565 { 272, 99, 1.221730164 },
5566 { 273, 94, 1.239188479 },
5567 { 277, 90, 1.25664606 },
5568 { 157, 48, 1.274088705 },
5569 { 279, 80, 1.291550147 },
5570 { 362, 97, 1.308990773 },
5571 { 373, 93, 1.326448578 },
5572 { 420, 97, 1.343823596 },
5573 { 207, 44, 1.361353157 },
5574 { 427, 83, 1.378810994 },
5575 { 414, 73, 1.396261926 },
5576 { 322, 51, 1.413716057 },
5577 { 185, 26, 1.431170275 },
5578 { 790, 97, 1.448623034 },
5579 { 333, 35, 1.466075711 },
5580 { 1063, 93, 1.483530284 },
5581 { 1330, 93, 1.500985147 },
5582 { 706, 37, 1.518436297 },
5583 { 315, 11, 1.535889876 },
5584 { 3953, 69, 1.553343002 },
5590 static const QList<rationalTangent> rationalTangents
5592 { 1, 10, qDegreesToRadians( 5.71059 ) },
5593 { 1, 5, qDegreesToRadians( 11.3099 ) },
5594 { 1, 4, qDegreesToRadians( 14.0362 ) },
5595 { 1, 4, qDegreesToRadians( 18.4349 ) },
5596 { 1, 2, qDegreesToRadians( 26.5651 ) },
5597 { 2, 3, qDegreesToRadians( 33.6901 ) },
5598 { 1, 1, qDegreesToRadians( 45.0 ) },
5599 { 3, 2, qDegreesToRadians( 56.3099 ) },
5600 { 2, 1, qDegreesToRadians( 63.4349 ) },
5601 { 3, 1, qDegreesToRadians( 71.5651 ) },
5602 { 4, 1, qDegreesToRadians( 75.9638 ) },
5603 { 10, 1, qDegreesToRadians( 84.2894 ) },
5606 const int quadrant {
static_cast<int>( angleRad / M_PI_2 ) };
5607 Q_ASSERT( quadrant >= 0 && quadrant <= 3 );
5619 angleRad -= M_PI / 2;
5629 angleRad -= M_PI + M_PI_2;
5651 for (
int idx = 0; idx < rationalTangents.count(); ++idx )
5653 const auto item = rationalTangents.at( idx );
5654 if (
qgsDoubleNear( item.angle, angleRad, 10E-3 ) || item.angle > angleRad )
5661 const rationalTangent bTan { rationalTangents.at( rTanIdx ) };
5662 angleRad = bTan.angle;
5663 const double k { bTan.q *height *width / std::cos( angleRad ) };
5664 const int hcfH { std::gcd( bTan.p * height, bTan.q * width ) };
5665 const int hcfW { std::gcd( bTan.q * height, bTan.p * width ) };
5666 const int W1 {
static_cast<int>( std::round( k / hcfW ) ) };
5667 const int H1 {
static_cast<int>( std::round( k / hcfH ) ) };
5680 angleRad += M_PI / 2;
5693 angleRad += M_PI + M_PI_2;
5704template <
typename Functor>
5707 sl->
setId( generateId() );
5715template <
typename Functor>
5749 maskSl->clearMasks();
5752 if (
QgsSymbol *subSymbol = maskSl->subSymbol() )
5763 if ( clipGeometries.empty() )
5766 if ( bounds.isNull() )
5767 return clipGeometries;
5771 clipGeometries.erase(
5772 std::remove_if( clipGeometries.begin(), clipGeometries.end(), [&boundsRect](
const QgsGeometry & geometry )
5774 return !geometry.boundingBoxIntersects( boundsRect );
5775 } ), clipGeometries.end() );
5777 return clipGeometries;
@ PreferVector
Prefer vector-based rendering, when the result will still be visually near-identical to a raster-base...
MarkerClipMode
Marker clipping modes.
@ CompletelyWithin
Render complete markers wherever the completely fall within the polygon shape.
@ NoClipping
No clipping, render complete markers.
@ Shape
Clip to polygon shape.
@ CentroidWithin
Render complete markers wherever their centroid falls within the polygon shape.
LineClipMode
Line clipping modes.
@ NoClipping
Lines are not clipped, will extend to shape's bounding box.
@ ClipPainterOnly
Applying clipping on the painter only (i.e. line endpoints will coincide with polygon bounding box,...
@ ClipToIntersection
Clip lines to intersection with polygon shape (slower) (i.e. line endpoints will coincide with polygo...
ScaleMethod
Scale methods.
@ ScaleDiameter
Calculate scale by the diameter.
@ ScaleArea
Calculate scale by the area.
QFlags< SymbolLayerUserFlag > SymbolLayerUserFlags
Symbol layer user flags.
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
JoinStyle
Join styles for buffers.
@ Bevel
Use beveled joins.
@ Round
Use rounded joins.
@ Miter
Use mitered joins.
RenderUnit
Rendering size units.
@ Percentage
Percentage of another measurement (e.g., canvas size, feature size).
@ Millimeters
Millimeters.
@ Points
Points (e.g., for font sizes).
@ Unknown
Mixed or unknown units.
@ MetersInMapUnits
Meters value as Map units.
EndCapStyle
End cap styles for buffers.
@ Flat
Flat cap (in line with start/end of line).
@ Square
Square cap (extends past start/end of line by buffer distance).
@ RenderSymbolPreview
The render is for a symbol preview only and map based properties may not be available,...
@ Antialiasing
Use antialiasing while drawing.
@ HighQualityImageTransforms
Enable high quality image transformations, which results in better appearance of scaled or rotated ra...
VertexMarkerType
Editing vertex markers, used for showing vertices during a edit operation.
@ SemiTransparentCircle
Semi-transparent circle marker.
QFlags< SymbolRenderHint > SymbolRenderHints
Symbol render hints.
QFlags< SymbolFlag > SymbolFlags
Symbol flags.
@ RendererShouldUseSymbolLevels
If present, indicates that a QgsFeatureRenderer using the symbol should use symbol levels for best re...
@ MultiPolygon
MultiPolygon.
@ MultiLineString
MultiLineString.
SymbolCoordinateReference
Symbol coordinate reference modes.
@ Feature
Relative to feature/shape being rendered.
@ Viewport
Relative to the whole viewport/output device.
Abstract base class for all geometries.
vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry.
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
const_part_iterator const_parts_end() const
Returns STL-style iterator pointing to the imaginary const part after the last part of the geometry.
vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
const_part_iterator const_parts_begin() const
Returns STL-style iterator pointing to the const first part of the geometry.
virtual bool 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.
QgsLineSymbol * clone() const override
Returns a deep copy of this 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.
double size() const
Returns the estimated size for the whole symbol, which is the maximum size of all marker symbol layer...
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
Special symbol layer that uses its sub symbol as a selective mask.
static QDomElement elseFilterExpression(QDomDocument &doc)
Creates an ElseFilter from doc.
static QDomElement expressionToOgcExpression(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr, bool requiresFilterElement=false)
Creates an OGC expression XML element from the exp expression with default values for the geometry na...
static QDomElement expressionToOgcFilter(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr)
Creates OGC filter XML element.
static QgsExpression * expressionFromOgcFilter(const QDomElement &element, QgsVectorLayer *layer=nullptr)
Parse XML with OGC filter into QGIS expression.
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
virtual bool saveProperties(QDomDocument &doc, QDomElement &element) const
Saves the current state of the effect to a DOM element.
Resolves relative paths into absolute paths and vice versa.
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
void setX(double x)
Sets the x value of the point.
static QString typeString()
Returns the string identifier for QgsPresetSchemeColorRamp.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Returns a new QgsPresetSchemeColorRamp color ramp created using the properties encoded in a string ma...
A grouped map of multiple QgsProperty objects, each referenced by an integer key value.
QSet< int > propertyKeys() const final
Returns a list of property keys contained within the collection.
QgsProperty property(int key) const final
Returns a matching property from the collection, if one exists.
A store for object properties.
bool isProjectColor() const
Returns true if the property is set to a linked project color.
bool isActive() const
Returns whether the property is currently active.
void setActive(bool active)
Sets whether the property is currently active.
A container for the context for various read/write operations on objects.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
A rectangle specified with double values.
Contains information about the context of a rendering operation.
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
void setDevicePixelRatio(float ratio)
Sets the device pixel ratio.
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
QgsExpressionContext & expressionContext()
Gets the expression context.
void setRasterizedRenderingPolicy(Qgis::RasterizedRenderingPolicy policy)
Sets the policy controlling when rasterisation of content during renders is permitted.
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected).
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
QVector< QgsGeometry > symbolLayerClipGeometries(const QString &symbolLayerId) const
Returns clipping geometries to be applied to the symbolLayer before rendering.
static QgsRenderContext fromQPainter(QPainter *painter)
Creates a default render context given a pixel based QPainter destination.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
A fill symbol layer which fills polygons with a repeated SVG file.
Stores properties relating to a screen.
double devicePixelRatio() const
Returns the ratio between physical pixels and device-independent pixels for the screen.
bool isValid() const
Returns true if the properties are valid.
void updateRenderContextForScreen(QgsRenderContext &context) const
Updates the settings in a render context to match the screen settings.
Renders polygons using a single fill and stroke color.
void setStrokeWidthMapUnitScale(const QgsMapUnitScale &scale)
void setStrokeWidthUnit(Qgis::RenderUnit unit)
Sets the units for the width of the fill's stroke.
void setPenJoinStyle(Qt::PenJoinStyle style)
void setStrokeWidth(double strokeWidth)
void setStrokeStyle(Qt::PenStyle strokeStyle)
void setStrokeColor(const QColor &strokeColor) override
Sets the stroke color for the symbol layer.
A simple line symbol layer, which renders lines using a line in a variety of styles (e....
bool tweakDashPatternOnCorners() const
Returns true if dash patterns tweaks should be applied on sharp corners, to ensure that a double-leng...
Qt::PenJoinStyle penJoinStyle() const
Returns the pen join style used to render the line (e.g.
double trimDistanceStart() const
Returns the trim distance for the start of the line, which dictates a length from the start of the li...
double trimDistanceEnd() const
Returns the trim distance for the end of the line, which dictates a length from the end of the line a...
bool useCustomDashPattern() const
Returns true if the line uses a custom dash pattern.
Qt::PenStyle penStyle() const
Returns the pen style used to render the line (e.g.
double dashPatternOffset() const
Returns the dash pattern offset, which dictates how far along the dash pattern the pattern should sta...
bool drawInsidePolygon() const
Returns true if the line should only be drawn inside polygons, and any portion of the line which fall...
bool alignDashPattern() const
Returns true if dash patterns should be aligned to the start and end of lines, by applying subtle twe...
Holds SLD export options and other information related to SLD export of a QGIS layer style.
void pushWarning(const QString &warning)
Pushes a warning message generated during the conversion.
void pushError(const QString &error)
Pushes a error message generated during the conversion.
virtual QgsStyle::StyleEntity type() const =0
Returns the type of style entity.
An interface for classes which can visit style entity (e.g.
@ SymbolRule
Rule based symbology or label child rule.
A symbol entity for QgsStyle databases.
bool isAnimated() const
Returns true if the symbol is animated.
double frameRate() const
Returns the symbol animation frame rate (in frames per second).
Contains settings relating to symbol buffers, which draw a "halo" effect around the symbol.
We may need stable references to symbol layers, when pointers to symbol layers are not usable (when a...
std::unique_ptr< QgsSymbolLayer > createSymbolLayerFromSld(const QString &name, QDomElement &element) const
create a new instance of symbol layer given symbol layer name and SLD
void resolvePaths(const QString &name, QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving) const
Resolve paths in properties of a particular symbol layer.
void resolveFonts(const QString &name, QVariantMap &properties, const QgsReadWriteContext &context) const
Resolve fonts from the properties of a particular symbol layer.
std::unique_ptr< QgsSymbolLayer > createSymbolLayer(const QString &name, const QVariantMap &properties=QVariantMap()) const
create a new instance of symbol layer given symbol layer name and properties
static bool externalMarkerFromSld(QDomElement &element, QString &path, QString &format, int &markIndex, QColor &color, double &size)
static QColor parseColor(const QString &colorStr, bool strictEval=false)
Attempts to parse a string as a color using a variety of common formats, including hex codes,...
static bool rotationFromSldElement(QDomElement &element, QString &rotationFunc)
static void createAnchorPointElement(QDomDocument &doc, QDomElement &element, QPointF anchor)
Creates a SE 1.1 anchor point element as a child of the specified element.
static void sortVariantList(QList< QVariant > &list, Qt::SortOrder order)
Sorts the passed list in requested order.
static Qgis::MarkerClipMode decodeMarkerClipMode(const QString &string, bool *ok=nullptr)
Decodes a string representing a marker clip mode.
static QPicture symbolLayerPreviewPicture(const QgsSymbolLayer *layer, Qgis::RenderUnit units, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::SymbolType parentSymbolType=Qgis::SymbolType::Hybrid)
Draws a symbol layer preview to a QPicture.
static bool hasExternalGraphic(QDomElement &element)
Checks if element contains an ExternalGraphic element with format "image/svg+xml".
static QString encodePenStyle(Qt::PenStyle style)
static bool needMarkerLine(QDomElement &element)
static QVector< qreal > decodeSldRealVector(const QString &s)
static bool needLinePatternFill(QDomElement &element)
static std::unique_ptr< QgsSymbol > symbolFromMimeData(const QMimeData *data)
Attempts to parse mime data as a symbol.
static void clearSymbolLayerIds(QgsSymbol *symbol)
Remove recursively unique id from all symbol symbol layers and set an empty string instead.
static QString encodeSldBrushStyle(Qt::BrushStyle style)
static Qt::PenJoinStyle decodePenJoinStyle(const QString &str)
static QgsArrowSymbolLayer::HeadType decodeArrowHeadType(const QVariant &value, bool *ok=nullptr)
Decodes a value representing an arrow head type.
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
static Q_DECL_DEPRECATED QSet< const QgsSymbolLayer * > toSymbolLayerPointers(const QgsFeatureRenderer *renderer, const QSet< QgsSymbolLayerId > &symbolLayerIds)
Converts a set of symbol layer id to a set of pointers to actual symbol layers carried by the feature...
static QVariant colorRampToVariant(const QString &name, QgsColorRamp *ramp)
Saves a color ramp to a QVariantMap, wrapped in a QVariant.
static void applyScaleDependency(QDomDocument &doc, QDomElement &ruleElem, QVariantMap &props)
Checks if the properties contain scaleMinDenom and scaleMaxDenom, if available, they are added into t...
static QgsStringMap evaluatePropertiesMap(const QMap< QString, QgsProperty > &propertiesMap, const QgsExpressionContext &context)
Evaluates a map of properties using the given context and returns a variant map with evaluated expres...
static void drawVertexMarker(double x, double y, QPainter &p, Qgis::VertexMarkerType type, int markerSize)
Draws a vertex symbol at (painter) coordinates x, y.
static Q_DECL_DEPRECATED bool createExpressionElement(QDomDocument &doc, QDomElement &element, const QString &function)
Creates a OGC Expression element based on the provided function expression.
static bool displacementFromSldElement(QDomElement &element, QPointF &offset)
static bool hasWellKnownMark(QDomElement &element)
static std::unique_ptr< QgsColorRamp > loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
static QString getSvgParametricPath(const QString &basePath, const QColor &fillColor, const QColor &strokeColor, double strokeWidth)
Encodes a reference to a parametric SVG into a path with parameters according to the SVG Parameters s...
static Q_DECL_DEPRECATED bool createFunctionElement(QDomDocument &doc, QDomElement &element, const QString &function)
Creates an OGC function element.
static std::unique_ptr< 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 QColor decodeColor(const QString &str)
static std::unique_ptr< QgsSymbolLayer > loadSymbolLayer(QDomElement &element, const QgsReadWriteContext &context)
Reads and returns symbol layer from XML. Caller is responsible for deleting the returned object.
static bool onlineResourceFromSldElement(QDomElement &element, QString &path, QString &format)
static QPointF polygonCentroid(const QPolygonF &points)
Calculate the centroid point of a QPolygonF.
static QIcon colorRampPreviewIcon(QgsColorRamp *ramp, QSize size, int padding=0)
Returns an icon preview for a color ramp.
static QString encodeBrushStyle(Qt::BrushStyle style)
static QString svgSymbolPathToName(const QString &path, const QgsPathResolver &pathResolver)
Determines an SVG symbol's name from its path.
static bool needRasterMarker(const QDomElement &element)
Checks if element contains an ExternalGraphic element that should translate to a raster marker.
static QPixmap colorRampPreviewPixmap(QgsColorRamp *ramp, QSize size, int padding=0, Qt::Orientation direction=Qt::Horizontal, bool flipDirection=false, bool drawTransparentBackground=true)
Returns a pixmap preview for a color ramp.
static QString encodeSldAlpha(int alpha)
static void externalGraphicToSld(QDomDocument &doc, QDomElement &element, const QString &path, const QString &mime, const QColor &color, double size=-1)
static QPointF polygonPointOnSurface(const QPolygonF &points, const QVector< QPolygonF > *rings=nullptr)
Calculate a point on the surface of a QPolygonF.
static void blurImageInPlace(QImage &image, QRect rect, int radius, bool alphaOnly)
Blurs an image in place, e.g. creating Qt-independent drop shadows.
static QList< double > prettyBreaks(double minimum, double maximum, int classes)
Computes a sequence of about 'classes' equally spaced round values which cover the range of values fr...
static QPointF toPoint(const QVariant &value, bool *ok=nullptr)
Converts a value to a point.
static void premultiplyColor(QColor &rgb, int alpha)
Converts a QColor into a premultiplied ARGB QColor value using a specified alpha value.
static void saveProperties(QVariantMap props, QDomDocument &doc, QDomElement &element)
Saves the map of properties to XML.
static void multiplyImageOpacity(QImage *image, qreal opacity)
Multiplies opacity of image pixel values with a (global) transparency value.
static bool functionFromSldElement(QDomElement &element, QString &function)
static bool saveColorsToGpl(QFile &file, const QString &paletteName, const QgsNamedColorList &colors)
Exports colors to a gpl GIMP palette file.
static std::unique_ptr< QgsSymbolLayer > createFillLayerFromSld(QDomElement &element)
Creates a new fill layer from a SLD DOM element.
static QColor parseColorWithAlpha(const QString &colorStr, bool &containsAlpha, bool strictEval=false)
Attempts to parse a string as a color using a variety of common formats, including hex codes,...
static bool hasSldSymbolizer(const QDomElement &element)
Returns true if a DOM element contains an SLD Symbolizer element.
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
static QSizeF toSize(const QVariant &value, bool *ok=nullptr)
Converts a value to a size.
static double rescaleUom(double size, Qgis::RenderUnit unit, const QVariantMap &props)
Rescales the given size based on the uomScale found in the props, if any is found,...
static bool needEllipseMarker(QDomElement &element)
static std::unique_ptr< QgsSymbolLayer > createMarkerLayerFromSld(QDomElement &element)
Creates a new marker layer from a SLD DOM element.
static QgsNamedColorList colorListFromMimeData(const QMimeData *data)
Attempts to parse mime data as a list of named colors.
static void clearSymbolLayerMasks(QgsSymbol *symbol)
Remove recursively masks from all symbol symbol layers.
static bool isSharpCorner(QPointF p1, QPointF p2, QPointF p3)
Returns true if the angle formed by the line p1 - p2 - p3 forms a "sharp" corner.
static QString ogrFeatureStylePen(double width, double mmScaleFactor, double mapUnitsScaleFactor, const QColor &c, Qt::PenJoinStyle joinStyle=Qt::MiterJoin, Qt::PenCapStyle capStyle=Qt::FlatCap, double offset=0.0, const QVector< qreal > *dashPattern=nullptr)
Create ogr feature style string for pen.
static Qt::PenCapStyle decodePenCapStyle(const QString &str)
static double rendererFrameRate(const QgsFeatureRenderer *renderer)
Calculates the frame rate (in frames per second) at which the given renderer must be redrawn.
static QgsStringMap getSvgParameterList(QDomElement &element)
static bool needSvgFill(QDomElement &element)
static bool createSymbolLayerListFromSld(QDomElement &element, Qgis::GeometryType geomType, QList< QgsSymbolLayer * > &layers)
Creates a symbol layer list from a DOM element.
static bool externalGraphicFromSld(QDomElement &element, QString &path, QString &mime, QColor &color, double &size)
static Q_DECL_DEPRECATED void parametricSvgToSld(QDomDocument &doc, QDomElement &graphicElem, const QString &path, const QColor &fillColor, double size, const QColor &strokeColor, double strokeWidth)
Encodes a reference to a parametric SVG into SLD, as a succession of parametric SVG using URL paramet...
static QIcon symbolLayerPreviewIcon(const QgsSymbolLayer *layer, Qgis::RenderUnit u, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::SymbolType parentSymbolType=Qgis::SymbolType::Hybrid, QgsMapLayer *mapLayer=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Draws a symbol layer preview to an icon.
static QString encodeSldLineCapStyle(Qt::PenCapStyle style)
static QString encodeSldUom(Qgis::RenderUnit unit, double *scaleFactor)
Encodes a render unit into an SLD unit of measure string.
static QList< QList< QPolygonF > > toQPolygonF(const QgsGeometry &geometry, Qgis::SymbolType type)
Converts a geometry to a set of QPolygonF objects representing how the geometry should be drawn for a...
static std::unique_ptr< QgsSymbol > loadSymbol(const QDomElement &element, const QgsReadWriteContext &context)
Attempts to load a symbol from a DOM element.
static QVector< qreal > decodeRealVector(const QString &s)
static bool lineFromSld(QDomElement &element, Qt::PenStyle &penStyle, QColor &color, double &width, Qt::PenJoinStyle *penJoinStyle=nullptr, Qt::PenCapStyle *penCapStyle=nullptr, QVector< qreal > *customDashPattern=nullptr, double *dashOffset=nullptr)
static QPainter::CompositionMode decodeBlendMode(const QString &s)
static Qgis::ScaleMethod decodeScaleMethod(const QString &str)
Decodes a symbol scale method from a string.
static Q_DECL_DEPRECATED void createOpacityElement(QDomDocument &doc, QDomElement &element, const QString &alphaFunc)
Creates SLD opacity element.
static std::unique_ptr< QgsSymbolLayer > createLineLayerFromSld(QDomElement &element)
Creates a new line layer from a SLD DOM element.
static QString ogrFeatureStyleBrush(const QColor &fillColr)
Create ogr feature style string for brush.
static bool pointInPolygon(const QPolygonF &points, QPointF point)
Calculate whether a point is within of a QPolygonF.
static QStringList listSvgFiles()
Returns a list of all available svg files.
static QString encodeLineClipMode(Qgis::LineClipMode mode)
Encodes a line clip mode to a string.
static QPixmap symbolPreviewPixmap(const QgsSymbol *symbol, QSize size, int padding=0, QgsRenderContext *customContext=nullptr, bool selected=false, const QgsExpressionContext *expressionContext=nullptr, const QgsLegendPatchShape *shape=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Returns a pixmap preview for a color ramp.
static bool convertPolygonSymbolizerToPointMarker(QDomElement &element, QList< QgsSymbolLayer * > &layerList)
Converts a polygon symbolizer element to a list of marker symbol layers.
static Qgis::LineClipMode decodeLineClipMode(const QString &string, bool *ok=nullptr)
Decodes a string representing a line clip mode.
static bool needSvgMarker(const QDomElement &element)
Checks if element contains an ExternalGraphic element that should translate to an SVG marker.
static QStringList listSvgFilesAt(const QString &directory)
Returns a list of svg files at the specified directory.
static bool needFontMarker(QDomElement &element)
static QString encodePenCapStyle(Qt::PenCapStyle style)
static QPointF pointOnLineWithDistance(QPointF startPoint, QPointF directionPoint, double distance)
Returns a point on the line from startPoint to directionPoint that is a certain distance away from th...
static QFont::Style decodeSldFontStyle(const QString &str)
static QSize tileSize(int width, int height, double &angleRad)
Calculate the minimum size in pixels of a symbol tile given the symbol width and height and the symbo...
static QString fieldOrExpressionFromExpression(QgsExpression *expression)
Returns a field name if the whole expression is just a name of the field .
static bool opacityFromSldElement(QDomElement &element, QString &alphaFunc)
static QString encodeSldFontWeight(int weight)
static Q_DECL_DEPRECATED void externalMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &path, const QString &format, int *markIndex=nullptr, const QColor &color=QColor(), double size=-1)
Exports a marker to an SLD definition.
static QMimeData * colorListToMimeData(const QgsNamedColorList &colorList, bool allFormats=true)
Creates mime data from a list of named colors.
static Qt::BrushStyle decodeBrushStyle(const QString &str)
static QVector< QgsGeometry > collectSymbolLayerClipGeometries(const QgsRenderContext &context, const QString &symbolLayerId, const QRectF &bounds)
Returns a list of the symbol layer clip geometries to be used for the symbol layer with the specified...
static Qt::PenCapStyle decodeSldLineCapStyle(const QString &str)
static QgsNamedColorList importColorsFromGpl(QFile &file, bool &ok, QString &name)
Imports colors from a gpl GIMP palette file.
static QString encodeSize(QSizeF size)
Encodes a QSizeF to a string.
static QDomElement createVendorOptionElement(QDomDocument &doc, const QString &name, const QString &value)
static double sizeInPixelsFromSldUom(const QString &uom, double size)
Returns the size scaled in pixels according to the uom attribute.
static void appendPolyline(QPolygonF &target, const QPolygonF &line)
Appends a polyline line to an existing target polyline.
static bool wellKnownMarkerFromSld(QDomElement &element, QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle, double &strokeWidth, double &size)
Extracts properties from an SLD marker definition.
static void mergeScaleDependencies(double mScaleMinDenom, double mScaleMaxDenom, QVariantMap &props)
Merges the local scale limits, if any, with the ones already in the map, if any.
static QString colorToName(const QColor &color)
Returns a friendly display name for a color.
static int decodeSldAlpha(const QString &str)
static QString encodeSldLineJoinStyle(Qt::PenJoinStyle style)
static void createDisplacementElement(QDomDocument &doc, QDomElement &element, QPointF offset)
static QString svgSymbolNameToPath(const QString &name, const QgsPathResolver &pathResolver)
Determines an SVG symbol's path from its name.
static void drawStippledBackground(QPainter *painter, QRect rect)
static QList< QColor > parseColorList(const QString &colorStr)
Attempts to parse a string as a list of colors using a variety of common formats, including hex codes...
static QString encodeColor(const QColor &color)
static Qt::PenJoinStyle decodeSldLineJoinStyle(const QString &str)
static QVariantMap parseProperties(const QDomElement &element)
Parses the properties from XML and returns a map.
static bool fillFromSld(QDomElement &element, Qt::BrushStyle &brushStyle, QColor &color)
static Qgis::EndCapStyle penCapStyleToEndCapStyle(Qt::PenCapStyle style)
Converts a Qt pen cap style to a QGIS end cap style.
static QMimeData * symbolToMimeData(const QgsSymbol *symbol)
Creates new mime data from a symbol.
static QString encodeSldFontStyle(QFont::Style style)
static QColor colorFromMimeData(const QMimeData *data, bool &hasAlpha)
Attempts to parse mime data as a color.
static int decodeSldFontWeight(const QString &str)
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
static Q_DECL_DEPRECATED void fillToSld(QDomDocument &doc, QDomElement &element, Qt::BrushStyle brushStyle, const QColor &color=QColor())
Exports fill details to an SLD element.
static double polylineLength(const QPolygonF &polyline)
Returns the total length of a polyline.
static QDomElement saveColorRamp(const QString &name, const QgsColorRamp *ramp, QDomDocument &doc)
Encodes a color ramp's settings to an XML element.
static Qgis::RenderUnit decodeSldUom(const QString &str, double *scaleFactor=nullptr)
Decodes a SLD unit of measure string to a render unit.
static Q_DECL_DEPRECATED void createGeometryElement(QDomDocument &doc, QDomElement &element, const QString &geomFunc)
Creates an SLD geometry element.
static QgsArrowSymbolLayer::ArrowType decodeArrowType(const QVariant &value, bool *ok=nullptr)
Decodes a value representing an arrow type.
static void clearSymbolMap(QgsSymbolMap &symbols)
static Qt::BrushStyle decodeSldBrushStyle(const QString &str)
static void resetSymbolLayerIds(QgsSymbol *symbol)
Regenerate recursively unique id from all symbol symbol layers.
static double estimateMaxSymbolBleed(QgsSymbol *symbol, const QgsRenderContext &context)
Returns the maximum estimated bleed for the symbol.
static Q_DECL_DEPRECATED void wellKnownMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &name, const QColor &color, const QColor &strokeColor, Qt::PenStyle strokeStyle, double strokeWidth=-1, double size=-1)
Exports a marker to SLD.
static QString symbolProperties(QgsSymbol *symbol)
Returns a string representing the symbol.
static bool geometryFromSldElement(QDomElement &element, QString &geomFunc)
static QString encodeScaleMethod(Qgis::ScaleMethod scaleMethod)
Encodes a symbol scale method to a string.
static void createOnlineResourceElement(QDomDocument &doc, QDomElement &element, const QString &path, const QString &format)
static Qt::PenStyle decodePenStyle(const QString &str)
static Q_DECL_DEPRECATED void createRotationElement(QDomDocument &doc, QDomElement &element, const QString &rotationFunc)
Creates SLD rotation element.
static Qgis::SymbolCoordinateReference decodeCoordinateReference(const QString &string, bool *ok=nullptr)
Decodes a string representing a symbol coordinate reference mode.
static QgsSymbolMap loadSymbols(QDomElement &element, const QgsReadWriteContext &context)
Reads a collection of symbols from XML and returns them in a map. Caller is responsible for deleting ...
static QString encodePoint(QPointF point)
Encodes a QPointF to a string.
static Q_DECL_DEPRECATED void labelTextToSld(QDomDocument &doc, QDomElement &element, const QString &label, const QFont &font, const QColor &color=QColor(), double size=-1)
Exports label text to SLD.
static QDomElement saveSymbols(QgsSymbolMap &symbols, const QString &tagName, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a collection of symbols to XML with specified tagName for the top-level element.
static std::unique_ptr< QgsExpression > fieldOrExpressionToExpression(const QString &fieldOrExpression)
Returns a new valid expression instance for given field or expression string.
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
static QgsStringMap getVendorOptionList(QDomElement &element)
static Qgis::JoinStyle penJoinStyleToJoinStyle(Qt::PenJoinStyle style)
Converts a Qt pen joinstyle to a QGIS join style.
static QIcon symbolPreviewIcon(const QgsSymbol *symbol, QSize size, int padding=0, QgsLegendPatchShape *shape=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Returns an icon preview for a color ramp.
static QMimeData * colorToMimeData(const QColor &color)
Creates mime data from a color.
static bool condenseFillAndOutline(QgsFillSymbolLayer *fill, QgsLineSymbolLayer *outline)
Attempts to condense a fill and outline layer, by moving the outline layer to the fill symbol's strok...
static QPointF decodePoint(const QString &string)
Decodes a QSizeF from a string.
static QPolygonF polylineSubstring(const QPolygonF &polyline, double startOffset, double endOffset)
Returns the substring of a polyline which starts at startOffset from the beginning of the line and en...
static bool needPointPatternFill(QDomElement &element)
static QString encodeSldRealVector(const QVector< qreal > &v)
static QString encodeCoordinateReference(Qgis::SymbolCoordinateReference coordinateReference)
Encodes a symbol coordinate reference mode to a string.
static bool needRasterImageFill(QDomElement &element)
Checks if element contains a graphic fill with a raster image of type PNG, JPEG or GIF.
static QDomElement createSvgParameterElement(QDomDocument &doc, const QString &name, const QString &value)
static QString encodeMarkerClipMode(Qgis::MarkerClipMode mode)
Encodes a marker clip mode to a string.
static void lineToSld(QDomDocument &doc, QDomElement &element, Qt::PenStyle penStyle, const QColor &color, QgsSldExportContext &context, double width=-1, const Qt::PenJoinStyle *penJoinStyle=nullptr, const Qt::PenCapStyle *penCapStyle=nullptr, const QVector< qreal > *customDashPattern=nullptr, double dashOffset=0.0)
static QSizeF decodeSize(const QString &string)
Decodes a QSizeF from a string.
static bool hasExternalGraphicV2(const QDomElement &element, const QString format=QString())
Checks if element contains an ExternalGraphic element, if the optional format is specified it will al...
static QString encodeRealVector(const QVector< qreal > &v)
Abstract base class for symbol layers.
virtual QgsSymbolLayer * clone() const =0
Shall be reimplemented by subclasses to create a deep copy of the instance.
virtual bool setSubSymbol(QgsSymbol *symbol)
Sets layer's subsymbol. takes ownership of the passed symbol.
void setId(const QString &id)
Set symbol layer identifier This id has to be unique in the whole project.
bool isLocked() const
Returns true if the symbol layer colors are locked and the layer will ignore any symbol-level color c...
Property
Data definable properties.
virtual double estimateMaxBleed(const QgsRenderContext &context) const
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the layer.
virtual QVariantMap properties() const =0
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
bool enabled() const
Returns true if symbol layer is enabled and will be drawn.
virtual QString layerType() const =0
Returns a string that represents this layer type.
int renderingPass() const
Specifies the rendering pass in which this symbol layer should be rendered.
QString id() const
Returns symbol layer identifier This id is unique in the whole project.
virtual QgsSymbol * subSymbol()
Returns the symbol's sub symbol, if present.
Qgis::SymbolLayerUserFlags userFlags() const
Returns user-controlled flags which control the symbol layer's behavior.
virtual QColor color() const
Returns the "representative" color of the symbol layer.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol layer property definitions.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
virtual bool hasDataDefinedProperties() const
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
Encapsulates the context in which a symbol is being rendered.
void setOriginalGeometryType(Qgis::GeometryType type)
Sets the geometry type for the original feature geometry being rendered.
Abstract base class for all rendered symbols.
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol's property collection, used for data defined overrides.
QgsSymbolAnimationSettings & animationSettings()
Returns a reference to the symbol animation settings.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol property definitions.
Qgis::SymbolFlags flags() const
Returns flags for the symbol.
qreal opacity() const
Returns the opacity for the symbol.
bool clipFeaturesToExtent() const
Returns whether features drawn by the symbol will be clipped to the render context's extent.
QgsSymbolBufferSettings * bufferSettings()
Returns the symbol buffer settings, which control an optional "halo" effect around the symbol.
bool hasDataDefinedProperties() const
Returns whether the symbol utilizes any data defined properties.
QgsSymbolLayerList symbolLayers() const
Returns the list of symbol layers contained in the symbol.
Qgis::RenderUnit extentBufferSizeUnit() const
Returns the units for the buffer size.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
QColor color() const
Returns the symbol's color.
Qgis::SymbolType type() const
Returns the symbol's type.
double extentBuffer() const
Returns the symbol's extent buffer.
bool forceRHR() const
Returns true if polygon features drawn by the symbol will be reoriented to follow the standard right-...
static Q_INVOKABLE Qgis::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
static Qgis::GeometryType geometryType(Qgis::WkbType type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement.
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement.
QList< QPair< QColor, QString > > QgsNamedColorList
List of colors paired with a friendly display name identifying the color.
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).
T qgsgeometry_cast(QgsAbstractGeometry *geom)
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)
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.