52#include <QDomDocument>
60#include <QRegularExpression>
67using namespace Qt::StringLiterals;
69#define POINTS_TO_MM 2.83464567
73 return u
"%1,%2,%3,%4"_s.arg( color.red() ).arg( color.green() ).arg( color.blue() ).arg( color.alpha() );
78 const QStringList lst = str.split(
',' );
79 if ( lst.count() < 3 )
83 int red, green, blue, alpha;
85 green = lst[1].toInt();
86 blue = lst[2].toInt();
88 if ( lst.count() > 3 )
90 alpha = lst[3].toInt();
92 return QColor( red, green, blue, alpha );
97 return QString::number( alpha / 255.0,
'g', 2 );
103 double alpha = str.toDouble( &ok );
104 if ( !ok || alpha > 1 )
106 else if ( alpha < 0 )
115 case QFont::StyleNormal:
117 case QFont::StyleItalic:
119 case QFont::StyleOblique:
128 if ( str ==
"normal"_L1 )
return QFont::StyleNormal;
129 if ( str ==
"italic"_L1 )
return QFont::StyleItalic;
130 if ( str ==
"oblique"_L1 )
return QFont::StyleOblique;
131 return QFont::StyleNormal;
136 if ( weight == 50 )
return u
"normal"_s;
137 if ( weight == 75 )
return u
"bold"_s;
141 if ( weight < 0 )
return u
"100"_s;
142 if ( weight > 99 )
return u
"900"_s;
143 return QString::number( weight * 800 / 99 + 100 );
149 const int weight = str.toInt( &ok );
151 return static_cast< int >( QFont::Normal );
155 if ( weight > 900 )
return 99;
156 if ( weight < 100 )
return 0;
157 return ( weight - 100 ) * 99 / 800;
172 case Qt::DashDotLine:
173 return u
"dash dot"_s;
174 case Qt::DashDotDotLine:
175 return u
"dash dot dot"_s;
183 if ( str ==
"no"_L1 )
return Qt::NoPen;
184 if ( str ==
"solid"_L1 )
return Qt::SolidLine;
185 if ( str ==
"dash"_L1 )
return Qt::DashLine;
186 if ( str ==
"dot"_L1 )
return Qt::DotLine;
187 if ( str ==
"dash dot"_L1 )
return Qt::DashDotLine;
188 if ( str ==
"dash dot dot"_L1 )
return Qt::DashDotDotLine;
189 return Qt::SolidLine;
209 const QString cleaned = str.toLower().trimmed();
210 if ( cleaned ==
"bevel"_L1 )
211 return Qt::BevelJoin;
212 if ( cleaned ==
"miter"_L1 )
213 return Qt::MiterJoin;
214 if ( cleaned ==
"round"_L1 )
215 return Qt::RoundJoin;
216 return Qt::BevelJoin;
236 if ( str ==
"bevel"_L1 )
return Qt::BevelJoin;
237 if ( str ==
"mitre"_L1 )
return Qt::MiterJoin;
238 if ( str ==
"round"_L1 )
return Qt::RoundJoin;
239 return Qt::BevelJoin;
259 if ( str ==
"square"_L1 )
return Qt::SquareCap;
260 if ( str ==
"flat"_L1 )
return Qt::FlatCap;
261 if ( str ==
"round"_L1 )
return Qt::RoundCap;
262 return Qt::SquareCap;
282 if ( str ==
"square"_L1 )
return Qt::SquareCap;
283 if ( str ==
"butt"_L1 )
return Qt::FlatCap;
284 if ( str ==
"round"_L1 )
return Qt::RoundCap;
285 return Qt::SquareCap;
292 case Qt::SolidPattern :
294 case Qt::HorPattern :
295 return u
"horizontal"_s;
296 case Qt::VerPattern :
297 return u
"vertical"_s;
298 case Qt::CrossPattern :
300 case Qt::BDiagPattern :
301 return u
"b_diagonal"_s;
302 case Qt::FDiagPattern :
303 return u
"f_diagonal"_s;
304 case Qt::DiagCrossPattern :
305 return u
"diagonal_x"_s;
306 case Qt::Dense1Pattern :
308 case Qt::Dense2Pattern :
310 case Qt::Dense3Pattern :
312 case Qt::Dense4Pattern :
314 case Qt::Dense5Pattern :
316 case Qt::Dense6Pattern :
318 case Qt::Dense7Pattern :
329 if ( str ==
"solid"_L1 )
return Qt::SolidPattern;
330 if ( str ==
"horizontal"_L1 )
return Qt::HorPattern;
331 if ( str ==
"vertical"_L1 )
return Qt::VerPattern;
332 if ( str ==
"cross"_L1 )
return Qt::CrossPattern;
333 if ( str ==
"b_diagonal"_L1 )
return Qt::BDiagPattern;
334 if ( str ==
"f_diagonal"_L1 )
return Qt::FDiagPattern;
335 if ( str ==
"diagonal_x"_L1 )
return Qt::DiagCrossPattern;
336 if ( str ==
"dense1"_L1 )
return Qt::Dense1Pattern;
337 if ( str ==
"dense2"_L1 )
return Qt::Dense2Pattern;
338 if ( str ==
"dense3"_L1 )
return Qt::Dense3Pattern;
339 if ( str ==
"dense4"_L1 )
return Qt::Dense4Pattern;
340 if ( str ==
"dense5"_L1 )
return Qt::Dense5Pattern;
341 if ( str ==
"dense6"_L1 )
return Qt::Dense6Pattern;
342 if ( str ==
"dense7"_L1 )
return Qt::Dense7Pattern;
343 if ( str ==
"no"_L1 )
return Qt::NoBrush;
344 return Qt::SolidPattern;
351 case Qt::CrossPattern:
353 case Qt::DiagCrossPattern:
364 case Qt::BDiagPattern:
366 case Qt::FDiagPattern:
367 return u
"backslash"_s;
370 case Qt::Dense1Pattern:
371 case Qt::Dense2Pattern:
372 case Qt::Dense3Pattern:
373 case Qt::Dense4Pattern:
374 case Qt::Dense5Pattern:
375 case Qt::Dense6Pattern:
376 case Qt::Dense7Pattern:
386 if ( str ==
"horline"_L1 )
return Qt::HorPattern;
387 if ( str ==
"line"_L1 )
return Qt::VerPattern;
388 if ( str ==
"cross"_L1 )
return Qt::CrossPattern;
389 if ( str ==
"slash"_L1 )
return Qt::BDiagPattern;
390 if ( str ==
"backshash"_L1 )
return Qt::FDiagPattern;
391 if ( str ==
"x"_L1 )
return Qt::DiagCrossPattern;
393 if ( str.startsWith(
"brush://"_L1 ) )
409 case Qt::MPenCapStyle:
422 case Qt::SvgMiterJoin:
428 case Qt::MPenJoinStyle:
437 const QDomNodeList children = element.childNodes();
438 for (
int i = 0; i < children.size(); ++i )
440 const QDomElement childElement = children.at( i ).toElement();
441 if ( childElement.tagName() ==
"se:LineSymbolizer"_L1
442 || childElement.tagName() ==
"se:PointSymbolizer"_L1
443 || childElement.tagName() ==
"se:PolygonSymbolizer"_L1 )
451 const QString compareString =
string.trimmed();
455 if ( compareString.compare(
"feature"_L1, Qt::CaseInsensitive ) == 0 )
457 else if ( compareString.compare(
"viewport"_L1, Qt::CaseInsensitive ) == 0 )
467 switch ( coordinateReference )
472 return u
"viewport"_s;
483 const QString s = value.toString().toLower().trimmed();
484 if ( s ==
"single"_L1 )
486 else if ( s ==
"reversed"_L1 )
488 else if ( s ==
"double"_L1 )
490 else if ( value.toInt() == 1 )
492 else if ( value.toInt() == 2 )
494 else if ( value.toInt( &intOk ) == 0 && intOk )
508 const QString s = value.toString().toLower().trimmed();
509 if ( s ==
"plain"_L1 )
511 else if ( s ==
"lefthalf"_L1 )
513 else if ( s ==
"righthalf"_L1 )
515 else if ( value.toInt() == 1 )
517 else if ( value.toInt() == 2 )
519 else if ( value.toInt( &intOk ) == 0 && intOk )
529 const QString compareString =
string.trimmed();
533 if ( compareString.compare(
"no"_L1, Qt::CaseInsensitive ) == 0 )
535 else if ( compareString.compare(
"shape"_L1, Qt::CaseInsensitive ) == 0 )
537 else if ( compareString.compare(
"centroid_within"_L1, Qt::CaseInsensitive ) == 0 )
539 else if ( compareString.compare(
"completely_within"_L1, Qt::CaseInsensitive ) == 0 )
556 return u
"centroid_within"_s;
558 return u
"completely_within"_s;
565 const QString compareString =
string.trimmed();
569 if ( compareString.compare(
"no"_L1, Qt::CaseInsensitive ) == 0 )
571 else if ( compareString.compare(
"during_render"_L1, Qt::CaseInsensitive ) == 0 )
573 else if ( compareString.compare(
"before_render"_L1, Qt::CaseInsensitive ) == 0 )
588 return u
"during_render"_s;
590 return u
"before_render"_s;
602 QStringList lst = str.split(
',' );
603 if ( lst.count() != 2 )
604 return QPointF( 0, 0 );
605 return QPointF( lst[0].toDouble(), lst[1].toDouble() );
616 if ( value.userType() == QMetaType::Type::QVariantList )
618 const QVariantList list = value.toList();
619 if ( list.size() != 2 )
623 bool convertOk =
false;
624 const double x = list.at( 0 ).toDouble( &convertOk );
627 const double y = list.at( 1 ).toDouble( &convertOk );
632 return QPointF( x, y );
640 const QStringList list = value.toString().trimmed().split(
',' );
641 if ( list.count() != 2 )
643 bool convertOk =
false;
644 const double x = list.at( 0 ).toDouble( &convertOk );
647 const double y = list.at( 1 ).toDouble( &convertOk );
652 return QPointF( x, y );
666 QStringList lst =
string.split(
',' );
667 if ( lst.count() != 2 )
668 return QSizeF( 0, 0 );
669 return QSizeF( lst[0].toDouble(), lst[1].toDouble() );
680 if ( value.userType() == QMetaType::Type::QVariantList )
682 const QVariantList list = value.toList();
683 if ( list.size() != 2 )
687 bool convertOk =
false;
688 const double x = list.at( 0 ).toDouble( &convertOk );
691 const double y = list.at( 1 ).toDouble( &convertOk );
696 return QSizeF( x, y );
704 const QStringList list = value.toString().trimmed().split(
',' );
705 if ( list.count() != 2 )
707 bool convertOk =
false;
708 const double x = list.at( 0 ).toDouble( &convertOk );
711 const double y = list.at( 1 ).toDouble( &convertOk );
716 return QSizeF( x, y );
737 if ( str.startsWith(
"3x:"_L1 ) )
740 const QString chopped = str.mid( 3 );
741 lst = chopped.split(
',' );
745 lst = str.split(
',' );
747 if ( lst.count() < 2 )
750 double minScale = lst[0].toDouble();
752 minScale = minScale != 0 ? 1.0 / minScale : 0;
753 double maxScale = lst[1].toDouble();
755 maxScale = maxScale != 0 ? 1.0 / maxScale : 0;
757 if ( lst.count() < 6 )
777 *scaleFactor = 0.001;
778 return u
"http://www.opengeospatial.org/se/units/metre"_s;
783 return u
"http://www.opengeospatial.org/se/units/metre"_s;
790 *scaleFactor = 1 / 0.28;
799 if ( str ==
"http://www.opengeospatial.org/se/units/metre"_L1 )
805 else if ( str ==
"http://www.opengeospatial.org/se/units/foot"_L1 )
808 *scaleFactor = 0.3048;
823 QString vectorString;
824 QVector<qreal>::const_iterator it = v.constBegin();
825 for ( ; it != v.constEnd(); ++it )
827 if ( it != v.constBegin() )
829 vectorString.append(
';' );
831 vectorString.append( QString::number( *it ) );
838 QVector<qreal> resultVector;
840 const QStringList realList = s.split(
';' );
841 QStringList::const_iterator it = realList.constBegin();
842 for ( ; it != realList.constEnd(); ++it )
844 resultVector.append( it->toDouble() );
852 QString vectorString;
853 QVector<qreal>::const_iterator it = v.constBegin();
854 for ( ; it != v.constEnd(); ++it )
856 if ( it != v.constBegin() )
858 vectorString.append(
' ' );
860 vectorString.append( QString::number( *it ) );
867 QVector<qreal> resultVector;
869 const QStringList realList = s.split(
' ' );
870 QStringList::const_iterator it = realList.constBegin();
871 for ( ; it != realList.constEnd(); ++it )
873 resultVector.append( it->toDouble() );
881 QString encodedValue;
883 switch ( scaleMethod )
886 encodedValue = u
"diameter"_s;
889 encodedValue = u
"area"_s;
899 if ( str ==
"diameter"_L1 )
913 if ( s.compare(
"Lighten"_L1, Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Lighten;
914 if ( s.compare(
"Screen"_L1, Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Screen;
915 if ( s.compare(
"Dodge"_L1, Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorDodge;
916 if ( s.compare(
"Addition"_L1, Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Plus;
917 if ( s.compare(
"Darken"_L1, Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Darken;
918 if ( s.compare(
"Multiply"_L1, Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Multiply;
919 if ( s.compare(
"Burn"_L1, Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorBurn;
920 if ( s.compare(
"Overlay"_L1, Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Overlay;
921 if ( s.compare(
"SoftLight"_L1, Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_SoftLight;
922 if ( s.compare(
"HardLight"_L1, Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_HardLight;
923 if ( s.compare(
"Difference"_L1, Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Difference;
924 if ( s.compare(
"Subtract"_L1, Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Exclusion;
925 return QPainter::CompositionMode_SourceOver;
930 return QIcon(
symbolPreviewPixmap( symbol, size, padding,
nullptr,
false,
nullptr, shape, screen ) );
938 QPixmap pixmap( size * devicePixelRatio );
939 pixmap.setDevicePixelRatio( devicePixelRatio );
941 pixmap.fill( Qt::transparent );
943 painter.begin( &pixmap );
948 painter.setRenderHint( QPainter::Antialiasing );
949 painter.setRenderHint( QPainter::SmoothPixmapTransform );
959 size.setWidth( size.rwidth() - ( padding * 2 ) );
960 size.setHeight( size.rheight() - ( padding * 2 ) );
961 painter.translate( padding, padding );
971 std::unique_ptr<QgsSymbol> symbol_noDD( symbol->
clone( ) );
973 for (
const auto &layer : layers )
975 for (
int i = 0; i < layer->dataDefinedProperties().count(); ++i )
977 QgsProperty &prop = layer->dataDefinedProperties().property( i );
983 symbol_noDD->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape, screen );
987 std::unique_ptr<QgsSymbol> symbolClone( symbol->
clone( ) );
988 symbolClone->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape, screen );
1002 maxBleed = layerMaxBleed > maxBleed ? layerMaxBleed : maxBleed;
1012 painter.begin( &picture );
1013 painter.setRenderHint( QPainter::Antialiasing );
1023 switch ( parentSymbolType )
1038 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
1039 layerClone->drawPreviewIcon( symbolContext, size );
1047 QPixmap pixmap( size * devicePixelRatio );
1048 pixmap.setDevicePixelRatio( devicePixelRatio );
1049 pixmap.fill( Qt::transparent );
1051 painter.begin( &pixmap );
1052 painter.setRenderHint( QPainter::Antialiasing );
1070 switch ( parentSymbolType )
1085 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
1086 layerClone->drawPreviewIcon( symbolContext, size );
1088 return QIcon( pixmap );
1098 QPixmap pixmap( size );
1099 pixmap.fill( Qt::transparent );
1102 painter.begin( &pixmap );
1105 if ( drawTransparentBackground )
1106 drawStippledBackground( &painter, QRect( padding, padding, size.width() - padding * 2, size.height() - padding * 2 ) );
1110 switch ( direction )
1112 case Qt::Horizontal:
1114 for (
int i = 0; i < size.width(); i++ )
1116 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.width() ) );
1117 painter.setPen( pen );
1118 const int x = flipDirection ? size.width() - i - 1 : i;
1119 painter.drawLine( x, 0 + padding, x, size.height() - 1 - padding );
1126 for (
int i = 0; i < size.height(); i++ )
1128 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.height() ) );
1129 painter.setPen( pen );
1130 const int y = flipDirection ? size.height() - i - 1 : i;
1131 painter.drawLine( 0 + padding, y, size.width() - 1 - padding, y );
1144 uchar pixDataRGB[] = { 255, 255, 255, 255,
1149 const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
1151 const int width = ( rect.width() < rect.height() ) ?
1152 rect.width() / 2.5 : rect.height() / 2.5;
1153 const QPixmap pix = QPixmap::fromImage( img.scaled( width, width ) );
1156 brush.setTexture( pix );
1157 painter->fillRect( rect, brush );
1162 const qreal s = ( markerSize - 1 ) / 2.0;
1167 p.setPen( QColor( 50, 100, 120, 200 ) );
1168 p.setBrush( QColor( 200, 200, 210, 120 ) );
1169 p.drawEllipse( x - s, y - s, s * 2, s * 2 );
1172 p.setPen( QColor( 255, 0, 0 ) );
1173 p.drawLine( x - s, y + s, x + s, y - s );
1174 p.drawLine( x - s, y - s, x + s, y + s );
1186static QPolygonF makeOffsetGeometry(
const QgsPolylineXY &polyline )
1188 int i, pointCount = polyline.count();
1190 QPolygonF resultLine;
1191 resultLine.resize( pointCount );
1195 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1196 resultLine[i] = QPointF( tempPtr->
x(), tempPtr->
y() );
1200static QList<QPolygonF> makeOffsetGeometry(
const QgsPolygonXY &polygon )
1202 QList<QPolygonF> resultGeom;
1203 resultGeom.reserve( polygon.size() );
1204 for (
int ring = 0; ring < polygon.size(); ++ring )
1205 resultGeom.append( makeOffsetGeometry( polygon[ ring ] ) );
1211 QList<QPolygonF> resultLine;
1213 if ( polyline.count() < 2 )
1215 resultLine.append( polyline );
1219 unsigned int i, pointCount = polyline.count();
1222 QPointF *tempPtr = polyline.data();
1223 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1224 tempPolyline[i] =
QgsPointXY( tempPtr->rx(), tempPtr->ry() );
1227 if ( !tempGeometry.
isNull() )
1229 const int quadSegments = 0;
1230 const double miterLimit = 2.0;
1238 if ( !offsetGeom.
isNull() )
1240 tempGeometry = offsetGeom;
1245 resultLine.append( makeOffsetGeometry( line ) );
1250 resultLine.append( makeOffsetGeometry( tempGeometry.
asPolygon() ) );
1256 resultLine.reserve( tempMPolyline.count() );
1257 for (
int part = 0; part < tempMPolyline.count(); ++part )
1259 resultLine.append( makeOffsetGeometry( tempMPolyline[ part ] ) );
1266 resultLine.reserve( tempMPolygon.count() );
1267 for (
int part = 0; part < tempMPolygon.count(); ++part )
1269 resultLine.append( makeOffsetGeometry( tempMPolygon[ part ] ) );
1277 resultLine.append( polyline );
1286 if ( element.isNull() )
1290 QDomNode layerNode = element.firstChild();
1292 while ( !layerNode.isNull() )
1294 QDomElement e = layerNode.toElement();
1295 if ( !e.isNull() && e.tagName() !=
"data_defined_properties"_L1 && e.tagName() !=
"buffer"_L1 )
1297 if ( e.tagName() !=
"layer"_L1 )
1303 std::unique_ptr< QgsSymbolLayer > layer =
loadSymbolLayer( e, context );
1307 const QDomElement s = e.firstChildElement( u
"symbol"_s );
1310 std::unique_ptr< QgsSymbol > subSymbol(
loadSymbol( s, context ) );
1317 layers.append( layer.release() );
1319 for (
int i = 0; i < subSymbol->symbolLayerCount(); ++i )
1321 layers.append( subSymbol->symbolLayer( i )->clone() );
1326 const bool res = layer->setSubSymbol( subSymbol.release() );
1329 QgsDebugError( u
"symbol layer refused subsymbol: "_s + s.attribute(
"name" ) );
1331 layers.append( layer.release() );
1336 layers.append( layer.release() );
1341 layerNode = layerNode.nextSibling();
1344 if ( layers.isEmpty() )
1350 const QString symbolType = element.attribute( u
"type"_s );
1352 std::unique_ptr< QgsSymbol > symbol;
1353 if ( symbolType ==
"line"_L1 )
1354 symbol = std::make_unique< QgsLineSymbol >( layers );
1355 else if ( symbolType ==
"fill"_L1 )
1356 symbol = std::make_unique< QgsFillSymbol >( layers );
1357 else if ( symbolType ==
"marker"_L1 )
1358 symbol = std::make_unique< QgsMarkerSymbol >( layers );
1365 if ( element.hasAttribute( u
"outputUnit"_s ) )
1369 if ( element.hasAttribute( ( u
"mapUnitScale"_s ) ) )
1372 const double oldMin = element.attribute( u
"mapUnitMinScale"_s, u
"0.0"_s ).toDouble();
1373 mapUnitScale.
minScale = oldMin != 0 ? 1.0 / oldMin : 0;
1374 const double oldMax = element.attribute( u
"mapUnitMaxScale"_s, u
"0.0"_s ).toDouble();
1375 mapUnitScale.
maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
1376 symbol->setMapUnitScale( mapUnitScale );
1378 symbol->setOpacity( element.attribute( u
"alpha"_s, u
"1.0"_s ).toDouble() );
1379 symbol->setExtentBuffer( element.attribute( u
"extent_buffer"_s, u
"0.0"_s ).toDouble() );
1381 symbol->setClipFeaturesToExtent( element.attribute( u
"clip_to_extent"_s, u
"1"_s ).toInt() );
1382 symbol->setForceRHR( element.attribute( u
"force_rhr"_s, u
"0"_s ).toInt() );
1384 if ( element.attribute( u
"renderer_should_use_levels"_s, u
"0"_s ).toInt() )
1386 symbol->setFlags( flags );
1388 symbol->animationSettings().setIsAnimated( element.attribute( u
"is_animated"_s, u
"0"_s ).toInt() );
1389 symbol->animationSettings().setFrameRate( element.attribute( u
"frame_rate"_s, u
"10"_s ).toDouble() );
1391 if ( !element.firstChildElement( u
"buffer"_s ).isNull() )
1393 auto bufferSettings = std::make_unique< QgsSymbolBufferSettings >();
1394 bufferSettings->readXml( element, context );
1395 symbol->setBufferSettings( bufferSettings.release() );
1399 symbol->setBufferSettings(
nullptr );
1402 const QDomElement ddProps = element.firstChildElement( u
"data_defined_properties"_s );
1403 if ( !ddProps.isNull() )
1413 const QString layerClass = element.attribute( u
"class"_s );
1414 const bool locked = element.attribute( u
"locked"_s ).toInt();
1415 const bool enabled = element.attribute( u
"enabled"_s, u
"1"_s ).toInt();
1416 const int pass = element.attribute( u
"pass"_s ).toInt();
1417 const QString
id = element.attribute( u
"id"_s );
1418 const QString selectiveMaskingSetId = element.attribute( u
"selectiveMaskingSet"_s );
1432 layer->setLocked( locked );
1433 layer->setRenderingPass( pass );
1434 layer->setEnabled( enabled );
1435 layer->setUserFlags( userFlags );
1436 layer->setSelectiveMaskingSourceSetId( selectiveMaskingSetId );
1439 if ( !
id.isEmpty() )
1443 const QDomElement effectElem = element.firstChildElement( u
"effect"_s );
1444 if ( !effectElem.isNull() )
1448 layer->setPaintEffect( effect.release() );
1452 const QDomElement ddProps = element.firstChildElement( u
"data_defined_properties"_s );
1453 if ( !ddProps.isNull() )
1460 const QSet< int > oldKeys = prevProperties.
propertyKeys();
1461 for (
int key : oldKeys )
1463 if ( !layer->dataDefinedProperties().propertyKeys().contains( key ) )
1495 QDomElement symEl = doc.createElement( u
"symbol"_s );
1496 symEl.setAttribute( u
"type"_s, _nameForSymbolType( symbol->
type() ) );
1497 symEl.setAttribute( u
"name"_s, name );
1498 symEl.setAttribute( u
"alpha"_s, QString::number( symbol->
opacity() ) );
1502 symEl.setAttribute( u
"extent_buffer"_s, QString::number( symbol->
extentBuffer() ) );
1505 symEl.setAttribute( u
"force_rhr"_s, symbol->
forceRHR() ? u
"1"_s : u
"0"_s );
1507 symEl.setAttribute( u
"renderer_should_use_levels"_s, u
"1"_s );
1513 bufferSettings->writeXml( symEl, context );
1517 QDomElement ddProps = doc.createElement( u
"data_defined_properties"_s );
1519 symEl.appendChild( ddProps );
1525 QDomElement layerEl = doc.createElement( u
"layer"_s );
1526 layerEl.setAttribute( u
"class"_s, layer->
layerType() );
1527 layerEl.setAttribute( u
"enabled"_s, layer->
enabled() );
1528 layerEl.setAttribute( u
"locked"_s, layer->
isLocked() );
1530 layerEl.setAttribute( u
"id"_s, layer->
id() );
1546 QDomElement ddProps = doc.createElement( u
"data_defined_properties"_s );
1548 layerEl.appendChild( ddProps );
1552 const QString subname = u
"@%1@%2"_s.arg( name ).arg( i );
1553 const QDomElement subEl =
saveSymbol( subname, subSymbol, doc, context );
1554 layerEl.appendChild( subEl );
1556 symEl.appendChild( layerEl );
1564 QDomDocument doc( u
"qgis-symbol-definition"_s );
1567 QTextStream stream( &props );
1568 symbolElem.save( stream, -1 );
1574 QList<QgsSymbolLayer *> &layers )
1578 if ( element.isNull() )
1581 const QString symbolizerName = element.localName();
1583 if ( symbolizerName ==
"PointSymbolizer"_L1 )
1586 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1587 if ( graphicElem.isNull() )
1589 QgsDebugError( u
"Graphic element not found in PointSymbolizer"_s );
1600 layers.append( l.release() );
1610 layers.append( l.release() );
1620 layers.append( l.release() );
1632 if ( symbolizerName ==
"LineSymbolizer"_L1 )
1635 const QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
1636 if ( strokeElem.isNull() )
1638 QgsDebugError( u
"Stroke element not found in LineSymbolizer"_s );
1651 layers.append( l.release() );
1661 layers.append( l.release() );
1673 if ( symbolizerName ==
"PolygonSymbolizer"_L1 )
1676 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
1677 const QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
1678 if ( fillElem.isNull() && strokeElem.isNull() )
1680 QgsDebugError( u
"neither Fill nor Stroke element not found in PolygonSymbolizer"_s );
1694 layers.append( l.release() );
1698 if ( lastLayer->
layerType() ==
"SimpleFill"_L1 || lastLayer->
layerType() ==
"SVGFill"_L1 )
1706 layers.append( l.release() );
1716 layers.append( l.release() );
1739 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
1740 if ( fillElem.isNull() )
1746 std::unique_ptr< QgsSymbolLayer > l;
1764 const QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
1765 if ( strokeElem.isNull() )
1771 std::unique_ptr< QgsSymbolLayer > l;
1783 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1784 if ( graphicElem.isNull() )
1790 std::unique_ptr< QgsSymbolLayer > l;
1813 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1814 if ( graphicElem.isNull() )
1817 const QDomElement externalGraphicElem = graphicElem.firstChildElement( u
"ExternalGraphic"_s );
1818 if ( externalGraphicElem.isNull() )
1822 const QDomElement formatElem = externalGraphicElem.firstChildElement( u
"Format"_s );
1823 if ( formatElem.isNull() )
1826 const QString elementFormat = formatElem.firstChild().nodeValue();
1827 if ( ! format.isEmpty() && elementFormat != format )
1829 QgsDebugMsgLevel(
"unsupported External Graphic format found: " + elementFormat, 4 );
1834 const QDomElement onlineResourceElem = externalGraphicElem.firstChildElement( u
"OnlineResource"_s );
1835 const QDomElement inlineContentElem = externalGraphicElem.firstChildElement( u
"InlineContent"_s );
1837 if ( !onlineResourceElem.isNull() )
1841 else if ( !inlineContentElem.isNull() )
1854 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1855 if ( graphicElem.isNull() )
1858 const QDomElement markElem = graphicElem.firstChildElement( u
"Mark"_s );
1859 if ( markElem.isNull() )
1862 const QDomElement wellKnownNameElem = markElem.firstChildElement( u
"WellKnownName"_s );
1863 return !wellKnownNameElem.isNull();
1869 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1870 if ( graphicElem.isNull() )
1873 const QDomElement markElem = graphicElem.firstChildElement( u
"Mark"_s );
1874 if ( markElem.isNull() )
1878 const QDomElement formatElem = markElem.firstChildElement( u
"Format"_s );
1879 if ( formatElem.isNull() )
1882 const QString format = formatElem.firstChild().nodeValue();
1883 if ( format !=
"ttf"_L1 )
1885 QgsDebugError(
"unsupported Graphic Mark format found: " + format );
1890 const QDomElement onlineResourceElem = markElem.firstChildElement( u
"OnlineResource"_s );
1891 const QDomElement inlineContentElem = markElem.firstChildElement( u
"InlineContent"_s );
1892 if ( !onlineResourceElem.isNull() )
1895 const QDomElement markIndexElem = markElem.firstChildElement( u
"MarkIndex"_s );
1896 if ( !markIndexElem.isNull() )
1899 else if ( !inlineContentElem.isNull() )
1920 QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1921 if ( graphicElem.isNull() )
1925 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
1927 if ( it.key() ==
"widthHeightFactor"_L1 )
1938 const QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
1939 if ( strokeElem.isNull() )
1942 QDomElement graphicStrokeElem = strokeElem.firstChildElement( u
"GraphicStroke"_s );
1943 if ( graphicStrokeElem.isNull() )
1951 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
1952 if ( fillElem.isNull() )
1955 const QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
1956 if ( graphicFillElem.isNull() )
1959 QDomElement graphicElem = graphicFillElem.firstChildElement( u
"Graphic"_s );
1960 if ( graphicElem.isNull() )
1966 QColor fillColor, strokeColor;
1967 double size, strokeWidth;
1968 Qt::PenStyle strokeStyle;
1969 if ( !
wellKnownMarkerFromSld( graphicElem, name, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
1972 if ( name !=
"horline"_L1 )
1980 const double angle = angleFunc.toDouble( &ok );
1986 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
1987 if ( fillElem.isNull() )
1990 const QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
1991 if ( graphicFillElem.isNull() )
1994 const QDomElement graphicElem = graphicFillElem.firstChildElement( u
"Graphic"_s );
1995 if ( graphicElem.isNull() )
1998 const QDomElement markElem = graphicElem.firstChildElement( u
"Mark"_s );
1999 if ( markElem.isNull() )
2007 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
2008 if ( fillElem.isNull() )
2011 QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
2012 if ( graphicFillElem.isNull() )
2020 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
2021 if ( fillElem.isNull() )
2024 QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
2025 if ( graphicFillElem.isNull() )
2045 QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
2046 QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
2050 bool validFill =
false, validStroke =
false;
2055 Qt::BrushStyle fillStyle;
2057 if (
fillFromSld( fillElem, fillStyle, fillColor ) )
2063 Qt::PenStyle strokeStyle;
2064 double strokeWidth = 1.0, dashOffset = 0.0;
2065 QVector<qreal> customDashPattern;
2067 if (
lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth,
2068 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2071 if ( validFill || validStroke )
2074 map[u
"name"_s] = u
"square"_s;
2077 map[u
"size"_s] = QString::number( 6 );
2078 map[u
"angle"_s] = QString::number( 0 );
2079 map[u
"offset"_s] =
encodePoint( QPointF( 0, 0 ) );
2086 bool validFill =
false, validStroke =
false;
2089 QString name, format;
2091 QColor fillColor, strokeColor;
2092 double strokeWidth = 1.0, size = 0.0, angle = 0.0;
2096 const QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
2097 if ( !graphicFillElem.isNull() )
2100 QDomElement graphicElem = graphicFillElem.firstChildElement( u
"Graphic"_s );
2101 if ( !graphicElem.isNull() )
2107 const QDomElement graphicChildElem = graphicElem.firstChildElement();
2108 while ( !graphicChildElem.isNull() )
2110 if ( graphicChildElem.localName() ==
"Mark"_L1 )
2113 const QDomElement wellKnownNameElem = graphicChildElem.firstChildElement( u
"WellKnownName"_s );
2114 if ( !wellKnownNameElem.isNull() )
2116 name = wellKnownNameElem.firstChild().nodeValue();
2122 if ( graphicChildElem.localName() ==
"ExternalGraphic"_L1 || graphicChildElem.localName() ==
"Mark"_L1 )
2125 const QDomElement formatElem = graphicChildElem.firstChildElement( u
"Format"_s );
2126 if ( formatElem.isNull() )
2129 format = formatElem.firstChild().nodeValue();
2133 if ( graphicChildElem.localName() ==
"ExternalGraphic"_L1 && format !=
"image/svg+xml"_L1 )
2138 if ( graphicChildElem.localName() ==
"Mark"_L1 && format !=
"ttf"_L1 )
2142 const QDomElement onlineResourceElem = graphicChildElem.firstChildElement( u
"OnlineResource"_s );
2143 const QDomElement inlineContentElem = graphicChildElem.firstChildElement( u
"InlineContent"_s );
2145 if ( !onlineResourceElem.isNull() )
2147 name = onlineResourceElem.attributeNS( u
"http://www.w3.org/1999/xlink"_s, u
"href"_s );
2149 if ( graphicChildElem.localName() ==
"Mark"_L1 && format ==
"ttf"_L1 )
2152 if ( name.startsWith(
"ttf://"_L1 ) )
2153 name = name.mid( 6 );
2156 const QDomElement markIndexElem = graphicChildElem.firstChildElement( u
"MarkIndex"_s );
2157 if ( markIndexElem.isNull() )
2161 const int v = markIndexElem.firstChild().nodeValue().toInt( &ok );
2172 else if ( !inlineContentElem.isNull() )
2182 if ( graphicChildElem.localName() ==
"Mark"_L1 )
2191 if ( found && graphicChildElem.localName() ==
"Mark"_L1 )
2198 Qt::BrushStyle markFillStyle;
2200 QDomElement markFillElem = graphicChildElem.firstChildElement( u
"Fill"_s );
2201 if (
fillFromSld( markFillElem, markFillStyle, fillColor ) )
2206 Qt::PenStyle strokeStyle;
2207 double strokeWidth = 1.0, dashOffset = 0.0;
2208 QVector<qreal> customDashPattern;
2210 QDomElement markStrokeElem = graphicChildElem.firstChildElement( u
"Stroke"_s );
2211 if (
lineFromSld( markStrokeElem, strokeStyle, strokeColor, strokeWidth,
2212 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2219 const QDomElement opacityElem = graphicElem.firstChildElement( u
"Opacity"_s );
2220 if ( !opacityElem.isNull() )
2221 fillColor.setAlpha(
decodeSldAlpha( opacityElem.firstChild().nodeValue() ) );
2223 const QDomElement sizeElem = graphicElem.firstChildElement( u
"Size"_s );
2224 if ( !sizeElem.isNull() )
2227 const double v = sizeElem.firstChild().nodeValue().toDouble( &ok );
2236 const double v = angleFunc.toDouble( &ok );
2246 if ( validFill || validStroke )
2248 if ( format ==
"image/svg+xml"_L1 )
2251 map[u
"name"_s] = name;
2252 map[u
"fill"_s] = fillColor.name();
2253 map[u
"outline"_s] = strokeColor.name();
2254 map[u
"outline-width"_s] = QString::number( strokeWidth );
2256 map[u
"size"_s] = QString::number( size );
2258 map[u
"angle"_s] = QString::number( angle );
2259 if ( !offset.isNull() )
2263 else if ( format ==
"ttf"_L1 )
2266 map[u
"font"_s] = name;
2267 map[u
"chr"_s] = markIndex;
2270 map[u
"size"_s] = QString::number( size );
2272 map[u
"angle"_s] = QString::number( angle );
2273 if ( !offset.isNull() )
2280 if ( layers.isEmpty() )
2283 layerList << layers;
2291 fillToSld( doc, element, context, brushStyle, color );
2296 QString patternName;
2297 switch ( brushStyle )
2302 case Qt::SolidPattern:
2303 if ( color.isValid() )
2306 if ( color.alpha() < 255 )
2311 case Qt::CrossPattern:
2312 case Qt::DiagCrossPattern:
2313 case Qt::HorPattern:
2314 case Qt::VerPattern:
2315 case Qt::BDiagPattern:
2316 case Qt::FDiagPattern:
2317 case Qt::Dense1Pattern:
2318 case Qt::Dense2Pattern:
2319 case Qt::Dense3Pattern:
2320 case Qt::Dense4Pattern:
2321 case Qt::Dense5Pattern:
2322 case Qt::Dense6Pattern:
2323 case Qt::Dense7Pattern:
2328 context.
pushWarning( QObject::tr(
"Brush style '%1' is not supported for SLD" ).arg( brushStyle ) );
2332 QDomElement graphicFillElem = doc.createElement( u
"se:GraphicFill"_s );
2333 element.appendChild( graphicFillElem );
2335 QDomElement graphicElem = doc.createElement( u
"se:Graphic"_s );
2336 graphicFillElem.appendChild( graphicElem );
2338 const QColor fillColor = patternName.startsWith(
"brush://"_L1 ) ? color : QColor();
2339 const QColor strokeColor = !patternName.startsWith(
"brush://"_L1 ) ? color : QColor();
2342 wellKnownMarkerToSld( doc, graphicElem, patternName, fillColor, strokeColor, Qt::SolidLine, context, -1, -1 );
2349 brushStyle = Qt::SolidPattern;
2350 color = QColor( 128, 128, 128 );
2352 if ( element.isNull() )
2354 brushStyle = Qt::NoBrush;
2359 const QDomElement graphicFillElem = element.firstChildElement( u
"GraphicFill"_s );
2361 if ( graphicFillElem.isNull() )
2364 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2366 QgsDebugMsgLevel( u
"found SvgParameter %1: %2"_s.arg( it.key(), it.value() ), 2 );
2368 if ( it.key() ==
"fill"_L1 )
2369 color = QColor( it.value() );
2370 else if ( it.key() ==
"fill-opacity"_L1 )
2376 QDomElement graphicElem = graphicFillElem.firstChildElement( u
"Graphic"_s );
2377 if ( graphicElem.isNull() )
2380 QString patternName = u
"square"_s;
2381 QColor fillColor, strokeColor;
2382 double strokeWidth, size;
2383 Qt::PenStyle strokeStyle;
2384 if ( !
wellKnownMarkerFromSld( graphicElem, patternName, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
2388 if ( brushStyle == Qt::NoBrush )
2391 const QColor
c = patternName.startsWith(
"brush://"_L1 ) ? fillColor : strokeColor;
2401 const Qt::PenJoinStyle *penJoinStyle,
const Qt::PenCapStyle *penCapStyle,
2402 const QVector<qreal> *customDashPattern,
double dashOffset )
2404 QVector<qreal> dashPattern;
2405 const QVector<qreal> *pattern = &dashPattern;
2407 if ( penStyle == Qt::CustomDashLine && !customDashPattern )
2409 context.
pushWarning( QObject::tr(
"WARNING: Custom dash pattern required but not provided. Using default dash pattern." ) );
2410 penStyle = Qt::DashLine;
2422 dashPattern.push_back( 4.0 );
2423 dashPattern.push_back( 2.0 );
2426 dashPattern.push_back( 1.0 );
2427 dashPattern.push_back( 2.0 );
2429 case Qt::DashDotLine:
2430 dashPattern.push_back( 4.0 );
2431 dashPattern.push_back( 2.0 );
2432 dashPattern.push_back( 1.0 );
2433 dashPattern.push_back( 2.0 );
2435 case Qt::DashDotDotLine:
2436 dashPattern.push_back( 4.0 );
2437 dashPattern.push_back( 2.0 );
2438 dashPattern.push_back( 1.0 );
2439 dashPattern.push_back( 2.0 );
2440 dashPattern.push_back( 1.0 );
2441 dashPattern.push_back( 2.0 );
2444 case Qt::CustomDashLine:
2445 Q_ASSERT( customDashPattern );
2446 pattern = customDashPattern;
2450 context.
pushWarning( QObject::tr(
"Pen style '%1' is not supported for SLD" ).arg( penStyle ) );
2454 if ( color.isValid() )
2457 if ( color.alpha() < 255 )
2464 else if ( width == 0 )
2474 if ( !pattern->isEmpty() )
2484 Qt::PenStyle &penStyle, QColor &color,
double &width,
2485 Qt::PenJoinStyle *penJoinStyle, Qt::PenCapStyle *penCapStyle,
2486 QVector<qreal> *customDashPattern,
double *dashOffset )
2490 penStyle = Qt::SolidLine;
2491 color = QColor( 0, 0, 0 );
2494 *penJoinStyle = Qt::BevelJoin;
2496 *penCapStyle = Qt::SquareCap;
2497 if ( customDashPattern )
2498 customDashPattern->clear();
2502 if ( element.isNull() )
2504 penStyle = Qt::NoPen;
2510 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2512 QgsDebugMsgLevel( u
"found SvgParameter %1: %2"_s.arg( it.key(), it.value() ), 2 );
2514 if ( it.key() ==
"stroke"_L1 )
2516 color = QColor( it.value() );
2518 else if ( it.key() ==
"stroke-opacity"_L1 )
2522 else if ( it.key() ==
"stroke-width"_L1 )
2525 const double w = it.value().toDouble( &ok );
2529 else if ( it.key() ==
"stroke-linejoin"_L1 && penJoinStyle )
2533 else if ( it.key() ==
"stroke-linecap"_L1 && penCapStyle )
2537 else if ( it.key() ==
"stroke-dasharray"_L1 )
2540 if ( !dashPattern.isEmpty() )
2544 bool dashPatternFound =
false;
2546 if ( dashPattern.count() == 2 )
2548 if ( dashPattern.at( 0 ) == 4.0 &&
2549 dashPattern.at( 1 ) == 2.0 )
2551 penStyle = Qt::DashLine;
2552 dashPatternFound =
true;
2554 else if ( dashPattern.at( 0 ) == 1.0 &&
2555 dashPattern.at( 1 ) == 2.0 )
2557 penStyle = Qt::DotLine;
2558 dashPatternFound =
true;
2561 else if ( dashPattern.count() == 4 )
2563 if ( dashPattern.at( 0 ) == 4.0 &&
2564 dashPattern.at( 1 ) == 2.0 &&
2565 dashPattern.at( 2 ) == 1.0 &&
2566 dashPattern.at( 3 ) == 2.0 )
2568 penStyle = Qt::DashDotLine;
2569 dashPatternFound =
true;
2572 else if ( dashPattern.count() == 6 )
2574 if ( dashPattern.at( 0 ) == 4.0 &&
2575 dashPattern.at( 1 ) == 2.0 &&
2576 dashPattern.at( 2 ) == 1.0 &&
2577 dashPattern.at( 3 ) == 2.0 &&
2578 dashPattern.at( 4 ) == 1.0 &&
2579 dashPattern.at( 5 ) == 2.0 )
2581 penStyle = Qt::DashDotDotLine;
2582 dashPatternFound =
true;
2587 if ( !dashPatternFound )
2589 if ( customDashPattern )
2591 penStyle = Qt::CustomDashLine;
2592 *customDashPattern = dashPattern;
2596 QgsDebugMsgLevel( u
"custom dash pattern required but not provided. Using default dash pattern."_s, 2 );
2597 penStyle = Qt::DashLine;
2602 else if ( it.key() ==
"stroke-dashoffset"_L1 && dashOffset )
2605 const double d = it.value().toDouble( &ok );
2615 const QString &path,
const QString &mime,
2616 const QColor &color,
double size )
2618 QDomElement externalGraphicElem = doc.createElement( u
"se:ExternalGraphic"_s );
2619 element.appendChild( externalGraphicElem );
2628 QDomElement sizeElem = doc.createElement( u
"se:Size"_s );
2630 element.appendChild( sizeElem );
2635 const QString &path,
const QColor &fillColor,
double size,
const QColor &strokeColor,
double strokeWidth )
2638 parametricSvgToSld( doc, graphicElem, path, fillColor, size, strokeColor, strokeWidth, context );
2648 graphicElem.appendChild( doc.createComment( u
"Parametric SVG"_s ) );
2649 const QString parametricPath =
getSvgParametricPath( path, fillColor, strokeColor, strokeWidth );
2652 graphicElem.appendChild( doc.createComment( u
"Plain SVG fallback, no parameters"_s ) );
2655 graphicElem.appendChild( doc.createComment( u
"Well known marker fallback"_s ) );
2661 QDomElement sizeElem = doc.createElement( u
"se:Size"_s );
2663 graphicElem.appendChild( sizeElem );
2670 if ( fillColor.isValid() )
2672 url.addQueryItem( u
"fill"_s, fillColor.name() );
2673 url.addQueryItem( u
"fill-opacity"_s,
encodeSldAlpha( fillColor.alpha() ) );
2677 url.addQueryItem( u
"fill"_s, u
"#000000"_s );
2678 url.addQueryItem( u
"fill-opacity"_s, u
"1"_s );
2680 if ( strokeColor.isValid() )
2682 url.addQueryItem( u
"outline"_s, strokeColor.name() );
2683 url.addQueryItem( u
"outline-opacity"_s,
encodeSldAlpha( strokeColor.alpha() ) );
2687 url.addQueryItem( u
"outline"_s, u
"#000000"_s );
2688 url.addQueryItem( u
"outline-opacity"_s, u
"1"_s );
2690 url.addQueryItem( u
"outline-width"_s, QString::number( strokeWidth ) );
2691 const QString params = url.toString( QUrl::FullyEncoded );
2692 if ( params.isEmpty() )
2698 return basePath +
"?" + params;
2703 QString &path, QString &mime,
2704 QColor &color,
double &size )
2709 QDomElement externalGraphicElem = element.firstChildElement( u
"ExternalGraphic"_s );
2710 if ( externalGraphicElem.isNull() )
2715 const QDomElement sizeElem = element.firstChildElement( u
"Size"_s );
2716 if ( !sizeElem.isNull() )
2719 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2728 const QString &path,
const QString &format,
int *markIndex,
2729 const QColor &color,
double size )
2737 QDomElement markElem = doc.createElement( u
"se:Mark"_s );
2738 element.appendChild( markElem );
2744 QDomElement markIndexElem = doc.createElement( u
"se:MarkIndex"_s );
2745 markIndexElem.appendChild( doc.createTextNode( QString::number( *markIndex ) ) );
2746 markElem.appendChild( markIndexElem );
2750 QDomElement fillElem = doc.createElement( u
"se:Fill"_s );
2751 fillToSld( doc, fillElem, context, Qt::SolidPattern, color );
2752 markElem.appendChild( fillElem );
2757 QDomElement sizeElem = doc.createElement( u
"se:Size"_s );
2759 element.appendChild( sizeElem );
2764 QString &path, QString &format,
int &markIndex,
2765 QColor &color,
double &size )
2773 QDomElement markElem = element.firstChildElement( u
"Mark"_s );
2774 if ( markElem.isNull() )
2779 const QDomElement markIndexElem = markElem.firstChildElement( u
"MarkIndex"_s );
2780 if ( !markIndexElem.isNull() )
2783 const int i = markIndexElem.firstChild().nodeValue().toInt( &ok );
2789 QDomElement fillElem = markElem.firstChildElement( u
"Fill"_s );
2790 Qt::BrushStyle b = Qt::SolidPattern;
2795 const QDomElement sizeElem = element.firstChildElement( u
"Size"_s );
2796 if ( !sizeElem.isNull() )
2799 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2808 const QString &name,
const QColor &color,
const QColor &strokeColor, Qt::PenStyle strokeStyle,
2809 double strokeWidth,
double size )
2812 wellKnownMarkerToSld( doc, element, name, color, strokeColor, strokeStyle, context, strokeWidth, size );
2817 QDomElement markElem = doc.createElement( u
"se:Mark"_s );
2818 element.appendChild( markElem );
2820 QDomElement wellKnownNameElem = doc.createElement( u
"se:WellKnownName"_s );
2821 wellKnownNameElem.appendChild( doc.createTextNode( name ) );
2822 markElem.appendChild( wellKnownNameElem );
2825 if ( color.isValid() )
2827 QDomElement fillElem = doc.createElement( u
"se:Fill"_s );
2828 fillToSld( doc, fillElem, context, Qt::SolidPattern, color );
2829 markElem.appendChild( fillElem );
2833 if ( strokeColor.isValid() )
2835 QDomElement strokeElem = doc.createElement( u
"se:Stroke"_s );
2836 lineToSld( doc, strokeElem, strokeStyle, strokeColor, context, strokeWidth );
2837 markElem.appendChild( strokeElem );
2843 QDomElement sizeElem = doc.createElement( u
"se:Size"_s );
2845 element.appendChild( sizeElem );
2850 QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle,
2851 double &strokeWidth,
double &size )
2857 strokeColor = QColor( 0, 0, 0 );
2861 const QDomElement markElem = element.firstChildElement( u
"Mark"_s );
2862 if ( markElem.isNull() )
2865 const QDomElement wellKnownNameElem = markElem.firstChildElement( u
"WellKnownName"_s );
2866 if ( !wellKnownNameElem.isNull() )
2868 name = wellKnownNameElem.firstChild().nodeValue();
2873 QDomElement fillElem = markElem.firstChildElement( u
"Fill"_s );
2874 Qt::BrushStyle b = Qt::SolidPattern;
2879 QDomElement strokeElem = markElem.firstChildElement( u
"Stroke"_s );
2880 lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth );
2884 const QDomElement sizeElem = element.firstChildElement( u
"Size"_s );
2885 if ( !sizeElem.isNull() )
2888 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2904 if ( !rotationFunc.isEmpty() )
2906 QDomElement rotationElem = doc.createElement( u
"se:Rotation"_s );
2908 element.appendChild( rotationElem );
2914 QDomElement rotationElem = element.firstChildElement( u
"Rotation"_s );
2915 if ( !rotationElem.isNull() )
2930 if ( !alphaFunc.isEmpty() )
2932 QDomElement opacityElem = doc.createElement( u
"se:Opacity"_s );
2934 element.appendChild( opacityElem );
2940 QDomElement opacityElem = element.firstChildElement( u
"Opacity"_s );
2941 if ( !opacityElem.isNull() )
2950 if ( offset.isNull() )
2953 QDomElement displacementElem = doc.createElement( u
"se:Displacement"_s );
2954 element.appendChild( displacementElem );
2956 QDomElement dispXElem = doc.createElement( u
"se:DisplacementX"_s );
2957 dispXElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.x(), 2 ) ) );
2959 QDomElement dispYElem = doc.createElement( u
"se:DisplacementY"_s );
2960 dispYElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.y(), 2 ) ) );
2962 displacementElem.appendChild( dispXElem );
2963 displacementElem.appendChild( dispYElem );
2970 QDomElement anchorElem = doc.createElement( u
"se:AnchorPoint"_s );
2971 element.appendChild( anchorElem );
2973 QDomElement anchorXElem = doc.createElement( u
"se:AnchorPointX"_s );
2974 anchorXElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.x() ) ) );
2976 QDomElement anchorYElem = doc.createElement( u
"se:AnchorPointY"_s );
2977 anchorYElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.y() ) ) );
2979 anchorElem.appendChild( anchorXElem );
2980 anchorElem.appendChild( anchorYElem );
2985 offset = QPointF( 0, 0 );
2987 const QDomElement displacementElem = element.firstChildElement( u
"Displacement"_s );
2988 if ( displacementElem.isNull() )
2991 const QDomElement dispXElem = displacementElem.firstChildElement( u
"DisplacementX"_s );
2992 if ( !dispXElem.isNull() )
2995 const double offsetX = dispXElem.firstChild().nodeValue().toDouble( &ok );
2997 offset.setX( offsetX );
3000 const QDomElement dispYElem = displacementElem.firstChildElement( u
"DisplacementY"_s );
3001 if ( !dispYElem.isNull() )
3004 const double offsetY = dispYElem.firstChild().nodeValue().toDouble( &ok );
3006 offset.setY( offsetY );
3013 const QString &label,
const QFont &font,
3014 const QColor &color,
double size )
3017 labelTextToSld( doc, element, label, font, context, color, size );
3022 QDomElement labelElem = doc.createElement( u
"se:Label"_s );
3023 labelElem.appendChild( doc.createTextNode( label ) );
3024 element.appendChild( labelElem );
3026 QDomElement fontElem = doc.createElement( u
"se:Font"_s );
3027 element.appendChild( fontElem );
3031 fontElem.appendChild( createSldParameterElement( doc,
"font-style",
encodeSldFontStyle( font.style() ) ) );
3032 fontElem.appendChild( createSldParameterElement( doc,
"font-weight",
encodeSldFontWeight( font.weight() ) ) );
3037 if ( color.isValid() )
3039 QDomElement fillElem = doc.createElement( u
"Fill"_s );
3040 fillToSld( doc, fillElem, context, Qt::SolidPattern, color );
3041 element.appendChild( fillElem );
3046 Qt::PenJoinStyle joinStyle,
3047 Qt::PenCapStyle capStyle,
3049 const QVector<qreal> *dashPattern )
3052 penStyle.append(
"PEN(" );
3053 penStyle.append(
"c:" );
3054 penStyle.append(
c.name() );
3055 penStyle.append(
",w:" );
3057 penStyle.append( QString::number( width * mmScaleFactor ) );
3058 penStyle.append(
"mm" );
3061 if ( dashPattern && !dashPattern->isEmpty() )
3063 penStyle.append(
",p:\"" );
3064 QVector<qreal>::const_iterator pIt = dashPattern->constBegin();
3065 for ( ; pIt != dashPattern->constEnd(); ++pIt )
3067 if ( pIt != dashPattern->constBegin() )
3069 penStyle.append(
' ' );
3071 penStyle.append( QString::number( *pIt * mapUnitScaleFactor ) );
3072 penStyle.append(
'g' );
3074 penStyle.append(
'\"' );
3078 penStyle.append(
",cap:" );
3082 penStyle.append(
'p' );
3085 penStyle.append(
'r' );
3089 penStyle.append(
'b' );
3093 penStyle.append(
",j:" );
3094 switch ( joinStyle )
3097 penStyle.append(
'b' );
3100 penStyle.append(
'r' );
3104 penStyle.append(
'm' );
3110 penStyle.append(
",dp:" );
3111 penStyle.append( QString::number( offset * mapUnitScaleFactor ) );
3112 penStyle.append(
'g' );
3115 penStyle.append(
')' );
3122 brushStyle.append(
"BRUSH(" );
3123 brushStyle.append(
"fc:" );
3124 brushStyle.append( fillColor.name() );
3125 brushStyle.append(
')' );
3137 if ( geomFunc.isEmpty() )
3140 QDomElement geometryElem = doc.createElement( u
"Geometry"_s );
3141 element.appendChild( geometryElem );
3171 QDomElement geometryElem = element.firstChildElement( u
"Geometry"_s );
3172 if ( geometryElem.isNull() )
3190 context.
pushError( QObject::tr(
"Parser error encountered when converting expression to SLD: %1 - Expression was: %2" ).arg( expr.
parserErrorString(), function ) );
3194 if ( !filterElem.isNull() )
3195 element.appendChild( filterElem );
3208 if ( function ==
"ELSE"_L1 )
3211 element.appendChild( filterElem );
3220 context.
pushError( QObject::tr(
"Parser error encountered when converting expression to SLD: %1 - Expression was: %2" ).arg( expr.
parserErrorString(), function ) );
3224 if ( !filterElem.isNull() )
3225 element.appendChild( filterElem );
3233 QDomElement elem = element;
3234 if ( element.tagName() !=
"Filter"_L1 )
3236 const QDomNodeList filterNodes = element.elementsByTagName( u
"Filter"_s );
3237 if ( !filterNodes.isEmpty() )
3239 elem = filterNodes.at( 0 ).toElement();
3243 if ( elem.isNull() )
3268 const QString &path,
const QString &format )
3272 QDomElement onlineResourceElem = doc.createElement( u
"se:OnlineResource"_s );
3273 onlineResourceElem.setAttribute( u
"xlink:type"_s, u
"simple"_s );
3274 onlineResourceElem.setAttribute( u
"xlink:href"_s, url );
3275 element.appendChild( onlineResourceElem );
3277 QDomElement formatElem = doc.createElement( u
"se:Format"_s );
3278 formatElem.appendChild( doc.createTextNode( format ) );
3279 element.appendChild( formatElem );
3286 const QDomElement onlineResourceElem = element.firstChildElement( u
"OnlineResource"_s );
3287 if ( onlineResourceElem.isNull() )
3290 path = QUrl::fromPercentEncoding( onlineResourceElem.attributeNS( u
"http://www.w3.org/1999/xlink"_s, u
"href"_s ).toUtf8() );
3292 const QDomElement formatElem = element.firstChildElement( u
"Format"_s );
3293 if ( formatElem.isNull() )
3296 format = formatElem.firstChild().nodeValue();
3303 QDomElement nodeElem = doc.createElement( u
"se:SvgParameter"_s );
3304 nodeElem.setAttribute( u
"name"_s, name );
3305 nodeElem.appendChild( doc.createTextNode( value ) );
3314 QDomElement paramElem = element.firstChildElement();
3315 while ( !paramElem.isNull() )
3317 if ( paramElem.localName() ==
"SvgParameter"_L1 || paramElem.localName() ==
"CssParameter"_L1 )
3319 const QString name = paramElem.attribute( u
"name"_s );
3320 if ( paramElem.firstChild().nodeType() == QDomNode::TextNode )
3322 value = paramElem.firstChild().nodeValue();
3326 if ( paramElem.firstChild().nodeType() == QDomNode::ElementNode &&
3327 paramElem.firstChild().localName() ==
"Literal"_L1 )
3330 value = paramElem.firstChild().firstChild().nodeValue();
3334 QgsDebugError( u
"unexpected child of %1"_s.arg( paramElem.localName() ) );
3338 if ( !name.isEmpty() && !value.isEmpty() )
3339 params[ name ] = value;
3342 paramElem = paramElem.nextSiblingElement();
3350 QDomElement nodeElem = doc.createElement( u
"se:VendorOption"_s );
3351 nodeElem.setAttribute( u
"name"_s, name );
3352 nodeElem.appendChild( doc.createTextNode( value ) );
3360 QDomElement paramElem = element.firstChildElement( u
"VendorOption"_s );
3361 while ( !paramElem.isNull() )
3363 const QString name = paramElem.attribute( u
"name"_s );
3364 const QString value = paramElem.firstChild().nodeValue();
3366 if ( !name.isEmpty() && !value.isEmpty() )
3367 params[ name ] = value;
3369 paramElem = paramElem.nextSiblingElement( u
"VendorOption"_s );
3379 if ( newSymbols.userType() == QMetaType::Type::QVariantMap )
3381 return newSymbols.toMap();
3388 QDomElement e = element.firstChildElement();
3389 while ( !e.isNull() )
3391 if ( e.tagName() ==
"prop"_L1 )
3393 const QString propKey = e.attribute( u
"k"_s );
3394 const QString propValue = e.attribute( u
"v"_s );
3395 props[propKey] = propValue;
3397 e = e.nextSiblingElement();
3414 QDomElement e = element.firstChildElement();
3416 while ( !e.isNull() )
3418 if ( e.tagName() ==
"symbol"_L1 )
3422 symbols.insert( e.attribute( u
"name"_s ), symbol.release() );
3428 e = e.nextSiblingElement();
3435 QStringList subsymbols;
3437 for ( QMap<QString, QgsSymbol *>::iterator it = symbols.begin(); it != symbols.end(); ++it )
3439 if ( it.key()[0] !=
'@' )
3443 subsymbols.append( it.key() );
3445 QStringList parts = it.key().split(
'@' );
3446 if ( parts.count() < 3 )
3448 QgsDebugError(
"found subsymbol with invalid name: " + it.key() );
3452 const QString symname = parts[1];
3453 const int symlayer = parts[2].toInt();
3455 if ( !symbols.contains( symname ) )
3457 QgsDebugError(
"subsymbol references invalid symbol: " + symname );
3465 QgsDebugError(
"subsymbol references invalid symbol layer: " + QString::number( symlayer ) );
3474 QgsDebugError(
"symbol layer refused subsymbol: " + it.key() );
3481 for (
int i = 0; i < subsymbols.count(); i++ )
3482 symbols.take( subsymbols[i] );
3489 QDomElement symbolsElem = doc.createElement( tagName );
3492 for ( QMap<QString, QgsSymbol *>::iterator its = symbols.begin(); its != symbols.end(); ++its )
3494 const QDomElement symEl =
saveSymbol( its.key(), its.value(), doc, context );
3495 symbolsElem.appendChild( symEl );
3503 qDeleteAll( symbols );
3512 std::unique_ptr< QMimeData >mimeData(
new QMimeData );
3514 QDomDocument symbolDoc;
3516 symbolDoc.appendChild( symbolElem );
3517 mimeData->setText( symbolDoc.toString() );
3520 mimeData->setColorData( symbol->
color() );
3522 return mimeData.release();
3530 const QString text = data->text();
3531 if ( !text.isEmpty() )
3536 if ( doc.setContent( text ) )
3538 elem = doc.documentElement();
3540 if ( elem.nodeName() !=
"symbol"_L1 )
3541 elem = elem.firstChildElement( u
"symbol"_s );
3552 const QString rampType = element.attribute( u
"type"_s );
3577 QDomElement rampEl = doc.createElement( u
"colorramp"_s );
3578 rampEl.setAttribute( u
"type"_s, ramp->
type() );
3579 rampEl.setAttribute( u
"name"_s, name );
3587 QVariantMap rampMap;
3589 rampMap.insert( u
"type"_s, ramp->
type() );
3590 rampMap.insert( u
"name"_s, name );
3592 const QVariantMap properties = ramp->
properties();
3594 QVariantMap propertyMap;
3595 for (
auto property = properties.constBegin(); property != properties.constEnd(); ++property )
3597 propertyMap.insert( property.key(), property.value() );
3600 rampMap.insert( u
"properties"_s, propertyMap );
3606 const QVariantMap rampMap = value.toMap();
3608 const QString rampType = rampMap.value( u
"type"_s ).toString();
3611 const QVariantMap propertyMap = rampMap.value( u
"properties"_s ).toMap();
3614 for (
auto property = propertyMap.constBegin(); property != propertyMap.constEnd(); ++property )
3616 props.insert( property.key(), property.value().toString() );
3638 if ( !color.isValid() )
3645 return color.name();
3650 QList<QColor> colors;
3653 const thread_local QRegularExpression sepCommaSpaceRegExp(
"(,|\\s)" );
3654 QStringList components = colorStr.simplified().split( sepCommaSpaceRegExp );
3655 QStringList::iterator it = components.begin();
3656 for ( ; it != components.end(); ++it )
3658 const QColor result =
parseColor( *it,
true );
3659 if ( result.isValid() )
3664 if ( colors.length() > 0 )
3670 const thread_local QRegularExpression sepCommaRegExp(
"(,|\n)" );
3671 components = colorStr.split( sepCommaRegExp );
3672 it = components.begin();
3673 for ( ; it != components.end(); ++it )
3675 const QColor result =
parseColor( *it,
true );
3676 if ( result.isValid() )
3681 if ( colors.length() > 0 )
3687 components = colorStr.simplified().split( QString(
' ' ) );
3688 it = components.begin();
3689 for ( ; it != components.end(); ++it )
3691 const QColor result =
parseColor( *it,
true );
3692 if ( result.isValid() )
3697 if ( colors.length() > 0 )
3703 components = colorStr.split(
'\n' );
3704 it = components.begin();
3705 for ( ; it != components.end(); ++it )
3707 const QColor result =
parseColor( *it,
true );
3708 if ( result.isValid() )
3721 QMimeData *mimeData =
new QMimeData;
3722 mimeData->setColorData( QVariant( color ) );
3723 mimeData->setText( color.name() );
3733 if ( mimeData->hasColor() )
3735 QColor mimeColor = mimeData->colorData().value<QColor>();
3736 if ( mimeColor.isValid() )
3744 if ( mimeData->hasText() )
3748 if ( textColor.isValid() )
3766 if ( data->hasFormat( u
"text/xml"_s ) )
3769 const QByteArray encodedData = data->data( u
"text/xml"_s );
3770 QDomDocument xmlDoc;
3771 xmlDoc.setContent( encodedData );
3773 const QDomElement dragDataElem = xmlDoc.documentElement();
3774 if ( dragDataElem.tagName() ==
"ColorSchemeModelDragData"_L1 )
3776 const QDomNodeList nodeList = dragDataElem.childNodes();
3777 const int nChildNodes = nodeList.size();
3778 QDomElement currentElem;
3780 for (
int i = 0; i < nChildNodes; ++i )
3782 currentElem = nodeList.at( i ).toElement();
3783 if ( currentElem.isNull() )
3788 QPair< QColor, QString> namedColor;
3790 namedColor.second = currentElem.attribute( u
"label"_s, QString() );
3792 mimeColors << namedColor;
3797 if ( mimeColors.length() == 0 && data->hasFormat( u
"application/x-colorobject-list"_s ) )
3800 const QByteArray encodedData = data->data( u
"application/x-colorobject-list"_s );
3801 QDomDocument xmlDoc;
3802 xmlDoc.setContent( encodedData );
3804 const QDomNodeList colorsNodes = xmlDoc.elementsByTagName( u
"colors"_s );
3805 if ( colorsNodes.length() > 0 )
3807 const QDomElement colorsElem = colorsNodes.at( 0 ).toElement();
3808 const QDomNodeList colorNodeList = colorsElem.childNodes();
3809 const int nChildNodes = colorNodeList.size();
3810 QDomElement currentElem;
3812 for (
int i = 0; i < nChildNodes; ++i )
3815 currentElem = colorNodeList.at( i ).toElement();
3816 if ( currentElem.isNull() )
3821 const QDomNodeList colorNodes = currentElem.elementsByTagName( u
"color"_s );
3822 const QDomNodeList nameNodes = currentElem.elementsByTagName( u
"name"_s );
3824 if ( colorNodes.length() > 0 )
3826 const QDomElement colorElem = colorNodes.at( 0 ).toElement();
3828 const QStringList colorParts = colorElem.text().simplified().split(
' ' );
3829 if ( colorParts.length() < 3 )
3834 const int red = colorParts.at( 0 ).toDouble() * 255;
3835 const int green = colorParts.at( 1 ).toDouble() * 255;
3836 const int blue = colorParts.at( 2 ).toDouble() * 255;
3837 QPair< QColor, QString> namedColor;
3838 namedColor.first = QColor( red, green, blue );
3839 if ( nameNodes.length() > 0 )
3841 const QDomElement nameElem = nameNodes.at( 0 ).toElement();
3842 namedColor.second = nameElem.text();
3844 mimeColors << namedColor;
3850 if ( mimeColors.length() == 0 && data->hasText() )
3854 QList< QColor >::iterator it = parsedColors.begin();
3855 for ( ; it != parsedColors.end(); ++it )
3857 mimeColors << qMakePair( *it, QString() );
3861 if ( mimeColors.length() == 0 && data->hasColor() )
3864 const QColor mimeColor = data->colorData().value<QColor>();
3865 if ( mimeColor.isValid() )
3867 mimeColors << qMakePair( mimeColor, QString() );
3877 QMimeData *mimeData =
new QMimeData();
3878 QDomDocument xmlDoc;
3879 QDomElement xmlRootElement = xmlDoc.createElement( u
"ColorSchemeModelDragData"_s );
3880 xmlDoc.appendChild( xmlRootElement );
3882 QgsNamedColorList::const_iterator colorIt = colorList.constBegin();
3883 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3885 QDomElement namedColor = xmlDoc.createElement( u
"NamedColor"_s );
3887 namedColor.setAttribute( u
"label"_s, ( *colorIt ).second );
3888 xmlRootElement.appendChild( namedColor );
3890 mimeData->setData( u
"text/xml"_s, xmlDoc.toByteArray() );
3898 colorIt = colorList.constBegin();
3899 QStringList colorListString;
3900 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3902 colorListString << ( *colorIt ).first.name();
3904 mimeData->setText( colorListString.join( QLatin1Char(
'\n' ) ) );
3907 if ( colorList.length() > 0 )
3909 mimeData->setColorData( QVariant( colorList.at( 0 ).first ) );
3917 if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3922 QTextStream stream( &file );
3924 stream <<
"GIMP Palette" << Qt::endl;
3925 if ( paletteName.isEmpty() )
3927 stream <<
"Name: QGIS Palette" << Qt::endl;
3931 stream <<
"Name: " << paletteName << Qt::endl;
3933 stream <<
"Columns: 4" << Qt::endl;
3934 stream <<
'#' << Qt::endl;
3936 for ( QgsNamedColorList::ConstIterator colorIt = colors.constBegin(); colorIt != colors.constEnd(); ++colorIt )
3938 const QColor color = ( *colorIt ).first;
3939 if ( !color.isValid() )
3943 stream << u
"%1 %2 %3"_s.arg( color.red(), 3 ).arg( color.green(), 3 ).arg( color.blue(), 3 );
3944 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << Qt::endl;
3955 if ( !file.open( QIODevice::ReadOnly ) )
3958 return importedColors;
3961 QTextStream in( &file );
3963 QString line = in.readLine();
3964 if ( !line.startsWith(
"GIMP Palette"_L1 ) )
3967 return importedColors;
3971 while ( !in.atEnd() && !line.startsWith(
"Name:"_L1 ) && !line.startsWith(
'#' ) )
3973 line = in.readLine();
3975 if ( line.startsWith(
"Name:"_L1 ) )
3977 const thread_local QRegularExpression nameRx(
"Name:\\s*(\\S.*)$" );
3978 const QRegularExpressionMatch match = nameRx.match( line );
3979 if ( match.hasMatch() )
3981 name = match.captured( 1 );
3986 while ( !in.atEnd() && !line.startsWith(
'#' ) )
3988 line = in.readLine();
3993 return importedColors;
3997 const thread_local QRegularExpression rx(
"^\\s*(\\d+)\\s+(\\d+)\\s+(\\d+)(\\s.*)?$" );
3998 while ( !in.atEnd() )
4000 line = in.readLine();
4001 const QRegularExpressionMatch match = rx.match( line );
4002 if ( !match.hasMatch() )
4006 const int red = match.captured( 1 ).toInt();
4007 const int green = match.captured( 2 ).toInt();
4008 const int blue = match.captured( 3 ).toInt();
4009 const QColor color = QColor( red, green, blue );
4010 if ( !color.isValid() )
4017 if ( rx.captureCount() > 3 )
4019 label = match.captured( 4 ).simplified();
4026 importedColors << qMakePair( color, label );
4031 return importedColors;
4044 const thread_local QRegularExpression hexColorAlphaRx(
"^\\s*#?([0-9a-fA-F]{6})([0-9a-fA-F]{2})\\s*$" );
4045 QRegularExpressionMatch match = hexColorAlphaRx.match( colorStr );
4048 if ( !match.hasMatch() && QColor::isValidColor( colorStr ) )
4051 parsedColor.setNamedColor( colorStr );
4052 if ( parsedColor.isValid() )
4054 containsAlpha =
false;
4060 if ( match.hasMatch() )
4062 const QString hexColor = match.captured( 1 );
4063 parsedColor.setNamedColor( u
"#"_s + hexColor );
4065 const int alphaHex = match.captured( 2 ).toInt( &alphaOk, 16 );
4067 if ( parsedColor.isValid() && alphaOk )
4069 parsedColor.setAlpha( alphaHex );
4070 containsAlpha =
true;
4078 const thread_local QRegularExpression hexColorRx2(
"^\\s*(?:[0-9a-fA-F]{3}){1,2}\\s*$" );
4079 if ( colorStr.indexOf( hexColorRx2 ) != -1 )
4082 parsedColor.setNamedColor( u
"#"_s + colorStr );
4083 if ( parsedColor.isValid() )
4085 containsAlpha =
false;
4092 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*$" );
4093 match = rgbFormatRx.match( colorStr );
4094 if ( match.hasMatch() )
4099 const int r = match.captured( 1 ).toInt( &rOk );
4100 const int g = match.captured( 2 ).toInt( &gOk );
4101 const int b = match.captured( 3 ).toInt( &bOk );
4103 if ( !rOk || !gOk || !bOk )
4105 const float rFloat = match.captured( 1 ).toFloat();
4106 const float gFloat = match.captured( 2 ).toFloat();
4107 const float bFloat = match.captured( 3 ).toFloat();
4108 parsedColor.setRgbF( rFloat / 255.0, gFloat / 255.0, bFloat / 255.0 );
4112 parsedColor.setRgb( r, g, b );
4115 if ( parsedColor.isValid() )
4117 containsAlpha =
false;
4123 const thread_local QRegularExpression hslFormatRx(
"^\\s*hsl\\(?\\s*(\\d+(?:\\.\\d*)?)\\s*,\\s*(\\d+(?:\\.\\d*)?)\\s*%\\s*,\\s*(\\d+(?:\\.\\d*)?)\\s*%\\s*\\)?\\s*;?\\s*$" );
4124 match = hslFormatRx.match( colorStr );
4125 if ( match.hasMatch() )
4130 const int h = match.captured( 1 ).toInt( &hOk );
4131 const int s = match.captured( 2 ).toInt( &sOk );
4132 const int l = match.captured( 3 ).toInt( &lOk );
4134 if ( !hOk || !sOk || !lOk )
4136 const float hFloat = match.captured( 1 ).toFloat();
4137 const float sFloat = match.captured( 2 ).toFloat();
4138 const float lFloat = match.captured( 3 ).toFloat();
4139 parsedColor.setHslF( hFloat / 360.0, sFloat / 100.0, lFloat / 100.0 );
4143 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0 );
4145 if ( parsedColor.isValid() )
4147 containsAlpha =
false;
4153 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*$" );
4154 match = rgbPercentFormatRx.match( colorStr );
4155 if ( match.hasMatch() )
4157 const double r = match.captured( 1 ).toDouble() / 100;
4158 const double g = match.captured( 2 ).toDouble() / 100;
4159 const double b = match.captured( 3 ).toDouble() / 100;
4160 parsedColor.setRgbF( r, g, b );
4161 if ( parsedColor.isValid() )
4163 containsAlpha =
false;
4169 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*$" );
4170 match = rgbaFormatRx.match( colorStr );
4171 if ( match.hasMatch() )
4176 const int r = match.captured( 1 ).toInt( &rOk );
4177 const int g = match.captured( 2 ).toInt( &gOk );
4178 const int b = match.captured( 3 ).toInt( &bOk );
4179 const double aDouble = match.captured( 4 ).toDouble();
4181 if ( !rOk || !gOk || !bOk )
4183 const float rFloat = match.captured( 1 ).toFloat();
4184 const float gFloat = match.captured( 2 ).toFloat();
4185 const float bFloat = match.captured( 3 ).toFloat();
4186 parsedColor.setRgbF( rFloat / 255.0, gFloat / 255.0, bFloat / 255.0, aDouble );
4190 const int a =
static_cast< int >( std::round( match.captured( 4 ).toDouble() * 255.0 ) );
4191 parsedColor.setRgb( r, g, b, a );
4193 if ( parsedColor.isValid() )
4195 containsAlpha =
true;
4201 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*$" );
4202 match = rgbaPercentFormatRx.match( colorStr );
4203 if ( match.hasMatch() )
4205 const double r = match.captured( 1 ).toDouble() / 100;
4206 const double g = match.captured( 2 ).toDouble() / 100;
4207 const double b = match.captured( 3 ).toDouble() / 100;
4208 const double a = match.captured( 4 ).toDouble();
4209 parsedColor.setRgbF( r, g, b, a );
4210 if ( parsedColor.isValid() )
4212 containsAlpha =
true;
4218 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*$" );
4219 match = hslaPercentFormatRx.match( colorStr );
4220 if ( match.hasMatch() )
4225 const int h = match.captured( 1 ).toInt( &hOk );
4226 const int s = match.captured( 2 ).toInt( &sOk );
4227 const int l = match.captured( 3 ).toInt( &lOk );
4228 const double aDouble = match.captured( 4 ).toDouble();
4230 if ( !hOk || !sOk || !lOk )
4232 const float hFloat = match.captured( 1 ).toFloat();
4233 const float sFloat = match.captured( 2 ).toFloat();
4234 const float lFloat = match.captured( 3 ).toFloat();
4235 parsedColor.setHslF( hFloat / 360.0, sFloat / 100.0, lFloat / 100.0, aDouble );
4239 const int a = std::round( aDouble * 255.0 );
4240 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0, a );
4243 if ( parsedColor.isValid() )
4245 containsAlpha =
true;
4262 const QImage::Format format = image->format();
4263 if ( format != QImage::Format_ARGB32_Premultiplied && format != QImage::Format_ARGB32 )
4270 for (
int heightIndex = 0; heightIndex < image->height(); ++heightIndex )
4272 QRgb *scanLine =
reinterpret_cast< QRgb *
>( image->scanLine( heightIndex ) );
4273 for (
int widthIndex = 0; widthIndex < image->width(); ++widthIndex )
4275 myRgb = scanLine[widthIndex];
4276 if ( format == QImage::Format_ARGB32_Premultiplied )
4277 scanLine[widthIndex] = qRgba( opacity * qRed( myRgb ), opacity * qGreen( myRgb ), opacity * qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4279 scanLine[widthIndex] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4287 const int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
4288 const int alpha = ( radius < 1 ) ? 16 : ( radius > 17 ) ? 1 : tab[radius - 1];
4290 if ( image.format() != QImage::Format_ARGB32_Premultiplied
4291 && image.format() != QImage::Format_RGB32 )
4293 image = image.convertToFormat( QImage::Format_ARGB32_Premultiplied );
4296 const int r1 = rect.top();
4297 const int r2 = rect.bottom();
4298 const int c1 = rect.left();
4299 const int c2 = rect.right();
4301 const int bpl = image.bytesPerLine();
4309 i1 = i2 = ( QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3 );
4311 for (
int col = c1; col <= c2; col++ )
4313 p = image.scanLine( r1 ) + col * 4;
4314 for (
int i = i1; i <= i2; i++ )
4315 rgba[i] = p[i] << 4;
4318 for (
int j = r1; j < r2; j++, p += bpl )
4319 for (
int i = i1; i <= i2; i++ )
4320 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4323 for (
int row = r1; row <= r2; row++ )
4325 p = image.scanLine( row ) + c1 * 4;
4326 for (
int i = i1; i <= i2; i++ )
4327 rgba[i] = p[i] << 4;
4330 for (
int j = c1; j < c2; j++, p += 4 )
4331 for (
int i = i1; i <= i2; i++ )
4332 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4335 for (
int col = c1; col <= c2; col++ )
4337 p = image.scanLine( r2 ) + col * 4;
4338 for (
int i = i1; i <= i2; i++ )
4339 rgba[i] = p[i] << 4;
4342 for (
int j = r1; j < r2; j++, p -= bpl )
4343 for (
int i = i1; i <= i2; i++ )
4344 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4347 for (
int row = r1; row <= r2; row++ )
4349 p = image.scanLine( row ) + c2 * 4;
4350 for (
int i = i1; i <= i2; i++ )
4351 rgba[i] = p[i] << 4;
4354 for (
int j = c1; j < c2; j++, p -= 4 )
4355 for (
int i = i1; i <= i2; i++ )
4356 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4362 if ( alpha != 255 && alpha > 0 )
4366 const double alphaFactor = alpha / 255.;
4367 int r = 0, g = 0, b = 0;
4368 rgb.getRgb( &r, &g, &b );
4373 rgb.setRgb( r, g, b, alpha );
4375 else if ( alpha == 0 )
4377 rgb.setRgb( 0, 0, 0, 0 );
4386 if ( !simpleFill || !simpleLine )
4410 if ( simpleLine->
offset() )
4428 if ( order == Qt::AscendingOrder )
4442 const double dx = directionPoint.x() - startPoint.x();
4443 const double dy = directionPoint.y() - startPoint.y();
4444 const double length = std::sqrt( dx * dx + dy * dy );
4445 const double scaleFactor = distance / length;
4446 return QPointF( startPoint.x() + dx * scaleFactor, startPoint.y() + dy * scaleFactor );
4456 for (
int i = 0; i < svgPaths.size(); i++ )
4458 const QDir dir( svgPaths[i] );
4459 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4460 for (
const QString &item : svgSubPaths )
4462 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4465 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4466 for (
const QString &item : svgFiles )
4469 list.append( dir.path() +
'/' + item );
4481 QStringList svgPaths;
4482 svgPaths.append( directory );
4484 for (
int i = 0; i < svgPaths.size(); i++ )
4486 const QDir dir( svgPaths[i] );
4487 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4488 for (
const QString &item : svgSubPaths )
4490 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4493 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4494 for (
const QString &item : svgFiles )
4496 list.append( dir.path() +
'/' + item );
4508 if ( n.startsWith(
"base64:"_L1 ) )
4512 if ( QFileInfo::exists( n ) )
4513 return QFileInfo( n ).canonicalFilePath();
4517 if ( name.contains(
"://"_L1 ) )
4519 const QUrl url( name );
4520 if ( url.isValid() && !url.scheme().isEmpty() )
4522 if ( url.scheme().compare(
"file"_L1, Qt::CaseInsensitive ) == 0 )
4525 name = url.toLocalFile();
4526 if ( QFile( name ).exists() )
4528 return QFileInfo( name ).canonicalFilePath();
4542 for (
int i = 0; i < svgPaths.size(); i++ )
4544 QString svgPath = svgPaths[i];
4545 if ( svgPath.endsWith( QChar(
'/' ) ) )
4556 const QString myLocalPath = svgPath + QDir::separator() + name;
4559 if ( QFile( myLocalPath ).exists() )
4562 return QFileInfo( myLocalPath ).canonicalFilePath();
4566 return pathResolver.
readPath( name );
4574 if ( p.startsWith(
"base64:"_L1 ) )
4577 if ( !QFileInfo::exists( p ) )
4580 QString path = QFileInfo( p ).canonicalFilePath();
4584 bool isInSvgPaths =
false;
4585 for (
int i = 0; i < svgPaths.size(); i++ )
4587 const QString dir = QFileInfo( svgPaths[i] ).canonicalFilePath();
4589 if ( !dir.isEmpty() && path.startsWith( dir ) )
4591 path = path.mid( dir.size() + 1 );
4592 isInSvgPaths =
true;
4605 const double *srcX = line->
xData();
4606 const double *srcY = line->
yData();
4608 QPolygonF thisRes( count );
4609 QPointF *dest = thisRes.data();
4610 for (
int i = 0; i < count; ++i )
4612 *dest++ = QPointF( *srcX++, *srcY++ );
4625 const std::unique_ptr< QgsLineString > straightened( curve->
curveToLine() );
4649 points << QPointF( ( *it ).x(), ( *it ).y() );
4653 points << QPointF( 0, 0 );
4655 return QList< QList<QPolygonF> >() << ( QList< QPolygonF >() << points );
4660 QList< QList<QPolygonF> > res;
4673 QList< QList<QPolygonF> > res;
4677 QList<QPolygonF> thisPart;
4696 return QList< QList<QPolygonF> >();
4699 return QList< QList<QPolygonF> >();
4706 double cx = 0, cy = 0;
4707 double area, sum = 0;
4708 for (
int i = points.count() - 1, j = 0; j < points.count(); i = j++ )
4710 const QPointF &p1 = points[i];
4711 const QPointF &p2 = points[j];
4712 area = p1.x() * p2.y() - p1.y() * p2.x();
4714 cx += ( p1.x() + p2.x() ) * area;
4715 cy += ( p1.y() + p2.y() ) * area;
4722 if ( points.count() >= 2 )
4723 return QPointF( ( points[0].x() + points[1].x() ) / 2, ( points[0].y() + points[1].y() ) / 2 );
4724 else if ( points.count() == 1 )
4732 return QPointF( cx, cy );
4739 if ( ( rings && rings->count() > 0 ) || !
pointInPolygon( points, centroid ) )
4741 unsigned int i, pointCount = points.count();
4743 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( points[i].x(), points[i].y() );
4749 for (
auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
4751 pointCount = ( *ringIt ).count();
4753 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( ( *ringIt )[i].x(), ( *ringIt )[i].y() );
4759 if ( !pointOnSurfaceGeom.
isNull() )
4762 centroid.
setX( point.
x() );
4763 centroid.setY( point.
y() );
4768 return QPointF( centroid.x(), centroid.y() );
4773 bool inside =
false;
4775 const double x = point.x();
4776 const double y = point.y();
4778 for (
int i = 0, j = points.count() - 1; i < points.count(); i++ )
4780 const QPointF &p1 = points[i];
4781 const QPointF &p2 = points[j];
4786 if ( ( p1.y() < y && p2.y() >= y ) || ( p2.y() < y && p1.y() >= y ) )
4788 if ( p1.x() + ( y - p1.y() ) / ( p2.y() - p1.y() ) * ( p2.x() - p1.x() ) <= x )
4799 if ( polyline.size() < 2 )
4802 double totalLength = 0;
4803 auto it = polyline.begin();
4805 for ( ; it != polyline.end(); ++it )
4807 const QPointF p2 = *it;
4808 const double segmentLength = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4809 totalLength += segmentLength;
4817 if ( polyline.size() < 2 )
4820 double totalLength = 0;
4821 auto it = polyline.begin();
4823 std::vector< double > segmentLengths( polyline.size() - 1 );
4824 auto segmentLengthIt = segmentLengths.begin();
4825 for ( ; it != polyline.end(); ++it )
4827 const QPointF p2 = *it;
4828 *segmentLengthIt = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4829 totalLength += *segmentLengthIt;
4835 if ( startOffset >= 0 && totalLength <= startOffset )
4837 if ( endOffset < 0 && totalLength <= -endOffset )
4840 const double startDistance = startOffset < 0 ? totalLength + startOffset : startOffset;
4841 const double endDistance = endOffset <= 0 ? totalLength + endOffset : endOffset;
4842 QPolygonF substringPoints;
4843 substringPoints.reserve( polyline.size() );
4845 it = polyline.begin();
4846 segmentLengthIt = segmentLengths.begin();
4849 bool foundStart =
false;
4850 if (
qgsDoubleNear( startDistance, 0.0 ) || startDistance < 0 )
4852 substringPoints << p1;
4856 double distanceTraversed = 0;
4857 for ( ; it != polyline.end(); ++it )
4859 const QPointF p2 = *it;
4860 if ( distanceTraversed < startDistance && distanceTraversed + *segmentLengthIt > startDistance )
4863 const double distanceToStart = startDistance - distanceTraversed;
4864 double startX, startY;
4866 substringPoints << QPointF( startX, startY );
4869 if ( foundStart && ( distanceTraversed + *segmentLengthIt > endDistance ) )
4872 const double distanceToEnd = endDistance - distanceTraversed;
4875 if ( substringPoints.last() != QPointF( endX, endY ) )
4876 substringPoints << QPointF( endX, endY );
4878 else if ( foundStart )
4880 if ( substringPoints.last() != QPointF( p2.x(), p2.y() ) )
4881 substringPoints << QPointF( p2.x(), p2.y() );
4884 distanceTraversed += *segmentLengthIt;
4885 if ( distanceTraversed > endDistance )
4892 if ( ( substringPoints.size() < 2 ) || ( substringPoints.size() == 2 && substringPoints.at( 0 ) == substringPoints.at( 1 ) ) )
4895 return substringPoints;
4900 double vertexAngle = M_PI - ( std::atan2( p3.y() - p2.y(), p3.x() - p2.x() ) - std::atan2( p2.y() - p1.y(), p2.x() - p1.x() ) );
4904 return vertexAngle < M_PI * 135.0 / 180.0 || vertexAngle > M_PI * 225.0 / 180.0;
4909 target.reserve( target.size() + line.size() );
4910 for (
const QPointF &pt : line )
4912 if ( !target.empty() && target.last() == pt )
4921 if ( fieldOrExpression.isEmpty() )
4924 auto expr = std::make_unique< QgsExpression >( fieldOrExpression );
4925 if ( !expr->hasParserError() )
4930 Q_ASSERT( !expr->hasParserError() );
4955 QList<double> breaks;
4958 breaks.append( maximum );
4962 const int minimumCount =
static_cast< int >( classes ) / 3;
4963 const double shrink = 0.75;
4964 const double highBias = 1.5;
4965 const double adjustBias = 0.5 + 1.5 * highBias;
4966 const int divisions = classes;
4967 const double h = highBias;
4970 const double dx = maximum - minimum;
4980 cell = std::max( std::fabs( minimum ), std::fabs( maximum ) );
4981 if ( adjustBias >= 1.5 * h + 0.5 )
4983 U = 1 + ( 1.0 / ( 1 + h ) );
4987 U = 1 + ( 1.5 / ( 1 + adjustBias ) );
4989 small = dx < ( cell * U * std::max( 1, divisions ) * 1e-07 * 3.0 );
4996 cell = 9 + cell / 10;
4997 cell = cell * shrink;
4999 if ( minimumCount > 1 )
5001 cell = cell / minimumCount;
5007 if ( divisions > 1 )
5009 cell = cell / divisions;
5012 if ( cell < 20 * 1e-07 )
5017 const double base = std::pow( 10.0, std::floor( std::log10( cell ) ) );
5019 if ( ( 2 * base ) - cell < h * ( cell - unit ) )
5022 if ( ( 5 * base ) - cell < adjustBias * ( cell - unit ) )
5025 if ( ( 10.0 * base ) - cell < h * ( cell - unit ) )
5032 int start = std::floor( minimum / unit + 1e-07 );
5033 int end = std::ceil( maximum / unit - 1e-07 );
5036 while ( start * unit > minimum + ( 1e-07 * unit ) )
5040 while ( end * unit < maximum - ( 1e-07 * unit ) )
5048 int k = std::floor( 0.5 + end - start );
5049 if ( k < minimumCount )
5051 k = minimumCount - k;
5055 start = start - k / 2 + k % 2;
5059 start = start - k / 2;
5060 end = end + k / 2 + k % 2;
5063 const double minimumBreak = start * unit;
5065 const int count = end - start;
5067 breaks.reserve( count );
5068 for (
int i = 1; i < count + 1; i++ )
5070 breaks.append( minimumBreak + i * unit );
5073 if ( breaks.isEmpty() )
5076 if ( breaks.first() < minimum )
5078 breaks[0] = minimum;
5080 if ( breaks.last() > maximum )
5082 breaks[breaks.count() - 1] = maximum;
5087 if ( minimum < 0.0 && maximum > 0.0 )
5089 QList<double> breaksMinusZero;
5090 for (
int i = 0; i < breaks.count(); i++ )
5092 breaksMinusZero.append( breaks[i] - 0.0 );
5095 for (
int i = 1; i < breaks.count(); i++ )
5097 if ( std::abs( breaksMinusZero[i] ) < std::abs( breaksMinusZero[i - 1] ) )
5100 breaks[posOfMin] = 0.0;
5109 bool roundToUnit =
false;
5112 if ( props.contains( u
"uomScale"_s ) )
5115 scale = props.value( u
"uomScale"_s ).toDouble( &ok );
5124 if ( props.value( u
"uom"_s ) ==
"http://www.opengeospatial.org/se/units/metre"_L1 )
5149 scale = 1 / 0.28 * 25.4;
5173 double rescaled = size * scale;
5178 rescaled = std::round( rescaled );
5185 const double x =
rescaleUom( point.x(), unit, props );
5186 const double y =
rescaleUom( point.y(), unit, props );
5187 return QPointF( x, y );
5192 QVector<qreal> result;
5193 QVector<qreal>::const_iterator it = array.constBegin();
5194 for ( ; it != array.constEnd(); ++it )
5196 result.append(
rescaleUom( *it, unit, props ) );
5203 if ( !props.value( u
"scaleMinDenom"_s, QString() ).toString().isEmpty() )
5205 QDomElement scaleMinDenomElem = doc.createElement( u
"se:MinScaleDenominator"_s );
5206 scaleMinDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( u
"scaleMinDenom"_s ).toString().toDouble() ) ) );
5207 ruleElem.appendChild( scaleMinDenomElem );
5210 if ( !props.value( u
"scaleMaxDenom"_s, QString() ).toString().isEmpty() )
5212 QDomElement scaleMaxDenomElem = doc.createElement( u
"se:MaxScaleDenominator"_s );
5213 scaleMaxDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( u
"scaleMaxDenom"_s ).toString().toDouble() ) ) );
5214 ruleElem.appendChild( scaleMaxDenomElem );
5223 const double parentScaleMinDenom = props.value( u
"scaleMinDenom"_s, u
"0"_s ).toString().toDouble( &ok );
5224 if ( !ok || parentScaleMinDenom <= 0 )
5225 props[ u
"scaleMinDenom"_s] = QString::number( mScaleMinDenom );
5227 props[ u
"scaleMinDenom"_s] = QString::number( std::max( parentScaleMinDenom, mScaleMinDenom ) );
5233 const double parentScaleMaxDenom = props.value( u
"scaleMaxDenom"_s, u
"0"_s ).toString().toDouble( &ok );
5234 if ( !ok || parentScaleMaxDenom <= 0 )
5235 props[ u
"scaleMaxDenom"_s] = QString::number( mScaleMaxDenom );
5237 props[ u
"scaleMaxDenom"_s] = QString::number( std::min( parentScaleMaxDenom, mScaleMaxDenom ) );
5245 if ( uom ==
"http://www.opengeospatial.org/se/units/metre"_L1 )
5247 scale = 1.0 / 0.00028;
5249 else if ( uom ==
"http://www.opengeospatial.org/se/units/foot"_L1 )
5251 scale = 304.8 / 0.28;
5258 return size * scale;
5267 SymbolLayerVisitor(
const QSet<QgsSymbolLayerId> &layerIds )
5268 : mSymbolLayerIds( layerIds )
5281 void visitSymbol(
const QgsSymbol *symbol,
const QString &identifier, QVector<int> rootPath )
5285 QVector<int> indexPath = rootPath;
5286 indexPath.append( idx );
5289 if ( mSymbolLayerIds.contains(
QgsSymbolLayerId( mCurrentRuleKey + identifier, indexPath ) ) )
5291 mSymbolLayers.insert( sl );
5297 visitSymbol( subSymbol, identifier, indexPath );
5306 if ( symbolEntity->symbol() )
5308 visitSymbol( symbolEntity->symbol(), leaf.
identifier, {} );
5314 QString mCurrentRuleKey;
5315 const QSet<QgsSymbolLayerId> &mSymbolLayerIds;
5316 QSet<const QgsSymbolLayer *> mSymbolLayers;
5320 SymbolLayerVisitor visitor( symbolLayerIds );
5321 renderer->
accept( &visitor );
5322 return visitor.mSymbolLayers;
5330 SymbolRefreshRateVisitor()
5342 void visitSymbol(
const QgsSymbol *symbol )
5359 if ( refreshRate == -1 || ( animatedMarker->frameRate() > refreshRate ) )
5360 refreshRate = animatedMarker->frameRate();
5364 visitSymbol( subSymbol );
5372 if (
QgsSymbol *symbol = qgis::down_cast<const QgsStyleSymbolEntity *>( leaf.
entity )->symbol() )
5374 visitSymbol( symbol );
5380 double refreshRate = -1;
5383 SymbolRefreshRateVisitor visitor;
5384 renderer->
accept( &visitor );
5385 return visitor.refreshRate;
5390 if ( !s || !context )
5416 size = markerSymbol->
size( *context );
5418 else if ( lineSymbol )
5420 size = lineSymbol->
width( *context );
5432 if ( minSize > 0 && size < minSize )
5436 else if ( maxSize > 0 && size > maxSize )
5448 std::unique_ptr< QgsMarkerSymbol > ms( markerSymbol->
clone() );
5449 ms->setSize( size );
5455 else if ( lineSymbol )
5457 std::unique_ptr< QgsLineSymbol > ls( lineSymbol->
clone() );
5458 ls->setWidth( size );
5470 QMap<QString, QgsProperty>::const_iterator paramIt = propertiesMap.constBegin();
5471 for ( ; paramIt != propertiesMap.constEnd(); ++paramIt )
5473 properties.insert( paramIt.key(), paramIt.value().valueAsString( context ) );
5481 angleRad = std::fmod( angleRad, M_PI * 2 );
5485 angleRad += M_PI * 2;
5489 struct rationalTangent
5501 static const QList<rationalTangent> __rationalTangents
5503 { 1, 57, 0.01754206006 },
5504 { 3, 86, 0.03486958155 },
5505 { 1, 19, 0.05258306161 },
5506 { 3, 43, 0.06965457373 },
5507 { 7, 80, 0.08727771295 },
5508 { 2, 19, 0.1048769387 },
5509 { 7, 57, 0.1221951707 },
5510 { 9, 64, 0.1397088743 },
5511 { 13, 82, 0.157228051 },
5512 { 3, 17, 0.174672199 },
5513 { 7, 36, 0.1920480172 },
5514 { 17, 80, 0.209385393 },
5515 { 3, 13, 0.2267988481 },
5516 { 1, 4, 0.2449786631 },
5517 { 26, 97, 0.2618852647 },
5518 { 27, 94, 0.2797041525 },
5519 { 26, 85, 0.2968446734 },
5520 { 13, 40, 0.3142318991 },
5521 { 21, 61, 0.3315541619 },
5522 { 4, 11, 0.3487710036 },
5523 { 38, 99, 0.3664967859 },
5524 { 40, 99, 0.383984624 },
5525 { 31, 73, 0.4015805401 },
5526 { 41, 92, 0.4192323938 },
5527 { 7, 15, 0.4366271598 },
5528 { 20, 41, 0.4538440015 },
5529 { 27, 53, 0.4711662643 },
5530 { 42, 79, 0.4886424026 },
5531 { 51, 92, 0.5061751436 },
5532 { 56, 97, 0.5235757641 },
5533 { 3, 5, 0.5404195003 },
5534 { 5, 8, 0.5585993153 },
5535 { 50, 77, 0.5759185996 },
5536 { 29, 43, 0.5933501462 },
5537 { 7, 10, 0.6107259644 },
5538 { 69, 95, 0.6281701124 },
5539 { 52, 69, 0.6458159195 },
5540 { 25, 32, 0.6632029927 },
5541 { 17, 21, 0.6805212247 },
5542 { 73, 87, 0.6981204504 },
5543 { 73, 84, 0.7154487784 },
5544 { 9, 10, 0.7328151018 },
5545 { 83, 89, 0.7505285818 },
5546 { 28, 29, 0.7678561033 },
5547 { 1, 1, 0.7853981634 },
5548 { 29, 28, 0.8029402235 },
5549 { 89, 83, 0.820267745 },
5550 { 10, 9, 0.837981225 },
5551 { 107, 93, 0.855284165 },
5552 { 87, 73, 0.8726758763 },
5553 { 121, 98, 0.8900374031 },
5554 { 32, 25, 0.9075933341 },
5555 { 69, 52, 0.9249804073 },
5556 { 128, 93, 0.9424647244 },
5557 { 10, 7, 0.9600703624 },
5558 { 43, 29, 0.9774461806 },
5559 { 77, 50, 0.9948777272 },
5560 { 8, 5, 1.012197011 },
5561 { 163, 98, 1.029475114 },
5562 { 168, 97, 1.047174539 },
5563 { 175, 97, 1.064668696 },
5564 { 126, 67, 1.082075603 },
5565 { 157, 80, 1.099534652 },
5566 { 203, 99, 1.117049384 },
5567 { 193, 90, 1.134452855 },
5568 { 146, 65, 1.151936673 },
5569 { 139, 59, 1.169382787 },
5570 { 99, 40, 1.186811703 },
5571 { 211, 81, 1.204257817 },
5572 { 272, 99, 1.221730164 },
5573 { 273, 94, 1.239188479 },
5574 { 277, 90, 1.25664606 },
5575 { 157, 48, 1.274088705 },
5576 { 279, 80, 1.291550147 },
5577 { 362, 97, 1.308990773 },
5578 { 373, 93, 1.326448578 },
5579 { 420, 97, 1.343823596 },
5580 { 207, 44, 1.361353157 },
5581 { 427, 83, 1.378810994 },
5582 { 414, 73, 1.396261926 },
5583 { 322, 51, 1.413716057 },
5584 { 185, 26, 1.431170275 },
5585 { 790, 97, 1.448623034 },
5586 { 333, 35, 1.466075711 },
5587 { 1063, 93, 1.483530284 },
5588 { 1330, 93, 1.500985147 },
5589 { 706, 37, 1.518436297 },
5590 { 315, 11, 1.535889876 },
5591 { 3953, 69, 1.553343002 },
5597 static const QList<rationalTangent> rationalTangents
5599 { 1, 10, qDegreesToRadians( 5.71059 ) },
5600 { 1, 5, qDegreesToRadians( 11.3099 ) },
5601 { 1, 4, qDegreesToRadians( 14.0362 ) },
5602 { 1, 4, qDegreesToRadians( 18.4349 ) },
5603 { 1, 2, qDegreesToRadians( 26.5651 ) },
5604 { 2, 3, qDegreesToRadians( 33.6901 ) },
5605 { 1, 1, qDegreesToRadians( 45.0 ) },
5606 { 3, 2, qDegreesToRadians( 56.3099 ) },
5607 { 2, 1, qDegreesToRadians( 63.4349 ) },
5608 { 3, 1, qDegreesToRadians( 71.5651 ) },
5609 { 4, 1, qDegreesToRadians( 75.9638 ) },
5610 { 10, 1, qDegreesToRadians( 84.2894 ) },
5613 const int quadrant {
static_cast<int>( angleRad / M_PI_2 ) };
5614 Q_ASSERT( quadrant >= 0 && quadrant <= 3 );
5626 angleRad -= M_PI / 2;
5636 angleRad -= M_PI + M_PI_2;
5658 for (
int idx = 0; idx < rationalTangents.count(); ++idx )
5660 const auto item = rationalTangents.at( idx );
5661 if (
qgsDoubleNear( item.angle, angleRad, 10E-3 ) || item.angle > angleRad )
5668 const rationalTangent bTan { rationalTangents.at( rTanIdx ) };
5669 angleRad = bTan.angle;
5670 const double k { bTan.q *height *width / std::cos( angleRad ) };
5671 const int hcfH { std::gcd( bTan.p * height, bTan.q * width ) };
5672 const int hcfW { std::gcd( bTan.q * height, bTan.p * width ) };
5673 const int W1 {
static_cast<int>( std::round( k / hcfW ) ) };
5674 const int H1 {
static_cast<int>( std::round( k / hcfH ) ) };
5687 angleRad += M_PI / 2;
5700 angleRad += M_PI + M_PI_2;
5711template <
typename Functor>
5714 sl->
setId( generateId() );
5722template <
typename Functor>
5756 maskSl->clearMasks();
5759 if (
QgsSymbol *subSymbol = maskSl->subSymbol() )
5770 if ( clipGeometries.empty() )
5773 if ( bounds.isNull() )
5774 return clipGeometries;
5778 clipGeometries.erase(
5779 std::remove_if( clipGeometries.begin(), clipGeometries.end(), [&boundsRect](
const QgsGeometry & geometry )
5781 return !geometry.boundingBoxIntersects( boundsRect );
5782 } ), clipGeometries.end() );
5784 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.
QString selectiveMaskingSourceSetId() const
Returns the selective masking source set ID for this symbol 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.