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 );
1431 layer->setLocked( locked );
1432 layer->setRenderingPass( pass );
1433 layer->setEnabled( enabled );
1434 layer->setUserFlags( userFlags );
1437 if ( !
id.isEmpty() )
1441 const QDomElement effectElem = element.firstChildElement( u
"effect"_s );
1442 if ( !effectElem.isNull() )
1446 layer->setPaintEffect( effect.release() );
1450 const QDomElement ddProps = element.firstChildElement( u
"data_defined_properties"_s );
1451 if ( !ddProps.isNull() )
1458 const QSet< int > oldKeys = prevProperties.
propertyKeys();
1459 for (
int key : oldKeys )
1461 if ( !layer->dataDefinedProperties().propertyKeys().contains( key ) )
1493 QDomElement symEl = doc.createElement( u
"symbol"_s );
1494 symEl.setAttribute( u
"type"_s, _nameForSymbolType( symbol->
type() ) );
1495 symEl.setAttribute( u
"name"_s, name );
1496 symEl.setAttribute( u
"alpha"_s, QString::number( symbol->
opacity() ) );
1500 symEl.setAttribute( u
"extent_buffer"_s, QString::number( symbol->
extentBuffer() ) );
1503 symEl.setAttribute( u
"force_rhr"_s, symbol->
forceRHR() ? u
"1"_s : u
"0"_s );
1505 symEl.setAttribute( u
"renderer_should_use_levels"_s, u
"1"_s );
1511 bufferSettings->writeXml( symEl, context );
1515 QDomElement ddProps = doc.createElement( u
"data_defined_properties"_s );
1517 symEl.appendChild( ddProps );
1523 QDomElement layerEl = doc.createElement( u
"layer"_s );
1524 layerEl.setAttribute( u
"class"_s, layer->
layerType() );
1525 layerEl.setAttribute( u
"enabled"_s, layer->
enabled() );
1526 layerEl.setAttribute( u
"locked"_s, layer->
isLocked() );
1528 layerEl.setAttribute( u
"id"_s, layer->
id() );
1542 QDomElement ddProps = doc.createElement( u
"data_defined_properties"_s );
1544 layerEl.appendChild( ddProps );
1548 const QString subname = u
"@%1@%2"_s.arg( name ).arg( i );
1549 const QDomElement subEl =
saveSymbol( subname, subSymbol, doc, context );
1550 layerEl.appendChild( subEl );
1552 symEl.appendChild( layerEl );
1560 QDomDocument doc( u
"qgis-symbol-definition"_s );
1563 QTextStream stream( &props );
1564 symbolElem.save( stream, -1 );
1570 QList<QgsSymbolLayer *> &layers )
1574 if ( element.isNull() )
1577 const QString symbolizerName = element.localName();
1579 if ( symbolizerName ==
"PointSymbolizer"_L1 )
1582 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1583 if ( graphicElem.isNull() )
1585 QgsDebugError( u
"Graphic element not found in PointSymbolizer"_s );
1596 layers.append( l.release() );
1606 layers.append( l.release() );
1616 layers.append( l.release() );
1628 if ( symbolizerName ==
"LineSymbolizer"_L1 )
1631 const QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
1632 if ( strokeElem.isNull() )
1634 QgsDebugError( u
"Stroke element not found in LineSymbolizer"_s );
1647 layers.append( l.release() );
1657 layers.append( l.release() );
1669 if ( symbolizerName ==
"PolygonSymbolizer"_L1 )
1672 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
1673 const QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
1674 if ( fillElem.isNull() && strokeElem.isNull() )
1676 QgsDebugError( u
"neither Fill nor Stroke element not found in PolygonSymbolizer"_s );
1690 layers.append( l.release() );
1694 if ( lastLayer->
layerType() ==
"SimpleFill"_L1 || lastLayer->
layerType() ==
"SVGFill"_L1 )
1702 layers.append( l.release() );
1712 layers.append( l.release() );
1735 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
1736 if ( fillElem.isNull() )
1742 std::unique_ptr< QgsSymbolLayer > l;
1760 const QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
1761 if ( strokeElem.isNull() )
1767 std::unique_ptr< QgsSymbolLayer > l;
1779 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1780 if ( graphicElem.isNull() )
1786 std::unique_ptr< QgsSymbolLayer > l;
1809 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1810 if ( graphicElem.isNull() )
1813 const QDomElement externalGraphicElem = graphicElem.firstChildElement( u
"ExternalGraphic"_s );
1814 if ( externalGraphicElem.isNull() )
1818 const QDomElement formatElem = externalGraphicElem.firstChildElement( u
"Format"_s );
1819 if ( formatElem.isNull() )
1822 const QString elementFormat = formatElem.firstChild().nodeValue();
1823 if ( ! format.isEmpty() && elementFormat != format )
1825 QgsDebugMsgLevel(
"unsupported External Graphic format found: " + elementFormat, 4 );
1830 const QDomElement onlineResourceElem = externalGraphicElem.firstChildElement( u
"OnlineResource"_s );
1831 const QDomElement inlineContentElem = externalGraphicElem.firstChildElement( u
"InlineContent"_s );
1833 if ( !onlineResourceElem.isNull() )
1837 else if ( !inlineContentElem.isNull() )
1850 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1851 if ( graphicElem.isNull() )
1854 const QDomElement markElem = graphicElem.firstChildElement( u
"Mark"_s );
1855 if ( markElem.isNull() )
1858 const QDomElement wellKnownNameElem = markElem.firstChildElement( u
"WellKnownName"_s );
1859 return !wellKnownNameElem.isNull();
1865 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1866 if ( graphicElem.isNull() )
1869 const QDomElement markElem = graphicElem.firstChildElement( u
"Mark"_s );
1870 if ( markElem.isNull() )
1874 const QDomElement formatElem = markElem.firstChildElement( u
"Format"_s );
1875 if ( formatElem.isNull() )
1878 const QString format = formatElem.firstChild().nodeValue();
1879 if ( format !=
"ttf"_L1 )
1881 QgsDebugError(
"unsupported Graphic Mark format found: " + format );
1886 const QDomElement onlineResourceElem = markElem.firstChildElement( u
"OnlineResource"_s );
1887 const QDomElement inlineContentElem = markElem.firstChildElement( u
"InlineContent"_s );
1888 if ( !onlineResourceElem.isNull() )
1891 const QDomElement markIndexElem = markElem.firstChildElement( u
"MarkIndex"_s );
1892 if ( !markIndexElem.isNull() )
1895 else if ( !inlineContentElem.isNull() )
1916 QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1917 if ( graphicElem.isNull() )
1921 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
1923 if ( it.key() ==
"widthHeightFactor"_L1 )
1934 const QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
1935 if ( strokeElem.isNull() )
1938 QDomElement graphicStrokeElem = strokeElem.firstChildElement( u
"GraphicStroke"_s );
1939 if ( graphicStrokeElem.isNull() )
1947 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
1948 if ( fillElem.isNull() )
1951 const QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
1952 if ( graphicFillElem.isNull() )
1955 QDomElement graphicElem = graphicFillElem.firstChildElement( u
"Graphic"_s );
1956 if ( graphicElem.isNull() )
1962 QColor fillColor, strokeColor;
1963 double size, strokeWidth;
1964 Qt::PenStyle strokeStyle;
1965 if ( !
wellKnownMarkerFromSld( graphicElem, name, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
1968 if ( name !=
"horline"_L1 )
1976 const double angle = angleFunc.toDouble( &ok );
1982 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
1983 if ( fillElem.isNull() )
1986 const QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
1987 if ( graphicFillElem.isNull() )
1990 const QDomElement graphicElem = graphicFillElem.firstChildElement( u
"Graphic"_s );
1991 if ( graphicElem.isNull() )
1994 const QDomElement markElem = graphicElem.firstChildElement( u
"Mark"_s );
1995 if ( markElem.isNull() )
2003 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
2004 if ( fillElem.isNull() )
2007 QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
2008 if ( graphicFillElem.isNull() )
2016 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
2017 if ( fillElem.isNull() )
2020 QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
2021 if ( graphicFillElem.isNull() )
2041 QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
2042 QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
2046 bool validFill =
false, validStroke =
false;
2051 Qt::BrushStyle fillStyle;
2053 if (
fillFromSld( fillElem, fillStyle, fillColor ) )
2059 Qt::PenStyle strokeStyle;
2060 double strokeWidth = 1.0, dashOffset = 0.0;
2061 QVector<qreal> customDashPattern;
2063 if (
lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth,
2064 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2067 if ( validFill || validStroke )
2070 map[u
"name"_s] = u
"square"_s;
2073 map[u
"size"_s] = QString::number( 6 );
2074 map[u
"angle"_s] = QString::number( 0 );
2075 map[u
"offset"_s] =
encodePoint( QPointF( 0, 0 ) );
2082 bool validFill =
false, validStroke =
false;
2085 QString name, format;
2087 QColor fillColor, strokeColor;
2088 double strokeWidth = 1.0, size = 0.0, angle = 0.0;
2092 const QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
2093 if ( !graphicFillElem.isNull() )
2096 QDomElement graphicElem = graphicFillElem.firstChildElement( u
"Graphic"_s );
2097 if ( !graphicElem.isNull() )
2103 const QDomElement graphicChildElem = graphicElem.firstChildElement();
2104 while ( !graphicChildElem.isNull() )
2106 if ( graphicChildElem.localName() ==
"Mark"_L1 )
2109 const QDomElement wellKnownNameElem = graphicChildElem.firstChildElement( u
"WellKnownName"_s );
2110 if ( !wellKnownNameElem.isNull() )
2112 name = wellKnownNameElem.firstChild().nodeValue();
2118 if ( graphicChildElem.localName() ==
"ExternalGraphic"_L1 || graphicChildElem.localName() ==
"Mark"_L1 )
2121 const QDomElement formatElem = graphicChildElem.firstChildElement( u
"Format"_s );
2122 if ( formatElem.isNull() )
2125 format = formatElem.firstChild().nodeValue();
2129 if ( graphicChildElem.localName() ==
"ExternalGraphic"_L1 && format !=
"image/svg+xml"_L1 )
2134 if ( graphicChildElem.localName() ==
"Mark"_L1 && format !=
"ttf"_L1 )
2138 const QDomElement onlineResourceElem = graphicChildElem.firstChildElement( u
"OnlineResource"_s );
2139 const QDomElement inlineContentElem = graphicChildElem.firstChildElement( u
"InlineContent"_s );
2141 if ( !onlineResourceElem.isNull() )
2143 name = onlineResourceElem.attributeNS( u
"http://www.w3.org/1999/xlink"_s, u
"href"_s );
2145 if ( graphicChildElem.localName() ==
"Mark"_L1 && format ==
"ttf"_L1 )
2148 if ( name.startsWith(
"ttf://"_L1 ) )
2149 name = name.mid( 6 );
2152 const QDomElement markIndexElem = graphicChildElem.firstChildElement( u
"MarkIndex"_s );
2153 if ( markIndexElem.isNull() )
2157 const int v = markIndexElem.firstChild().nodeValue().toInt( &ok );
2168 else if ( !inlineContentElem.isNull() )
2178 if ( graphicChildElem.localName() ==
"Mark"_L1 )
2187 if ( found && graphicChildElem.localName() ==
"Mark"_L1 )
2194 Qt::BrushStyle markFillStyle;
2196 QDomElement markFillElem = graphicChildElem.firstChildElement( u
"Fill"_s );
2197 if (
fillFromSld( markFillElem, markFillStyle, fillColor ) )
2202 Qt::PenStyle strokeStyle;
2203 double strokeWidth = 1.0, dashOffset = 0.0;
2204 QVector<qreal> customDashPattern;
2206 QDomElement markStrokeElem = graphicChildElem.firstChildElement( u
"Stroke"_s );
2207 if (
lineFromSld( markStrokeElem, strokeStyle, strokeColor, strokeWidth,
2208 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2215 const QDomElement opacityElem = graphicElem.firstChildElement( u
"Opacity"_s );
2216 if ( !opacityElem.isNull() )
2217 fillColor.setAlpha(
decodeSldAlpha( opacityElem.firstChild().nodeValue() ) );
2219 const QDomElement sizeElem = graphicElem.firstChildElement( u
"Size"_s );
2220 if ( !sizeElem.isNull() )
2223 const double v = sizeElem.firstChild().nodeValue().toDouble( &ok );
2232 const double v = angleFunc.toDouble( &ok );
2242 if ( validFill || validStroke )
2244 if ( format ==
"image/svg+xml"_L1 )
2247 map[u
"name"_s] = name;
2248 map[u
"fill"_s] = fillColor.name();
2249 map[u
"outline"_s] = strokeColor.name();
2250 map[u
"outline-width"_s] = QString::number( strokeWidth );
2252 map[u
"size"_s] = QString::number( size );
2254 map[u
"angle"_s] = QString::number( angle );
2255 if ( !offset.isNull() )
2259 else if ( format ==
"ttf"_L1 )
2262 map[u
"font"_s] = name;
2263 map[u
"chr"_s] = markIndex;
2266 map[u
"size"_s] = QString::number( size );
2268 map[u
"angle"_s] = QString::number( angle );
2269 if ( !offset.isNull() )
2276 if ( layers.isEmpty() )
2279 layerList << layers;
2287 fillToSld( doc, element, context, brushStyle, color );
2292 QString patternName;
2293 switch ( brushStyle )
2298 case Qt::SolidPattern:
2299 if ( color.isValid() )
2302 if ( color.alpha() < 255 )
2307 case Qt::CrossPattern:
2308 case Qt::DiagCrossPattern:
2309 case Qt::HorPattern:
2310 case Qt::VerPattern:
2311 case Qt::BDiagPattern:
2312 case Qt::FDiagPattern:
2313 case Qt::Dense1Pattern:
2314 case Qt::Dense2Pattern:
2315 case Qt::Dense3Pattern:
2316 case Qt::Dense4Pattern:
2317 case Qt::Dense5Pattern:
2318 case Qt::Dense6Pattern:
2319 case Qt::Dense7Pattern:
2324 context.
pushWarning( QObject::tr(
"Brush style '%1' is not supported for SLD" ).arg( brushStyle ) );
2328 QDomElement graphicFillElem = doc.createElement( u
"se:GraphicFill"_s );
2329 element.appendChild( graphicFillElem );
2331 QDomElement graphicElem = doc.createElement( u
"se:Graphic"_s );
2332 graphicFillElem.appendChild( graphicElem );
2334 const QColor fillColor = patternName.startsWith(
"brush://"_L1 ) ? color : QColor();
2335 const QColor strokeColor = !patternName.startsWith(
"brush://"_L1 ) ? color : QColor();
2338 wellKnownMarkerToSld( doc, graphicElem, patternName, fillColor, strokeColor, Qt::SolidLine, context, -1, -1 );
2345 brushStyle = Qt::SolidPattern;
2346 color = QColor( 128, 128, 128 );
2348 if ( element.isNull() )
2350 brushStyle = Qt::NoBrush;
2355 const QDomElement graphicFillElem = element.firstChildElement( u
"GraphicFill"_s );
2357 if ( graphicFillElem.isNull() )
2360 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2362 QgsDebugMsgLevel( u
"found SvgParameter %1: %2"_s.arg( it.key(), it.value() ), 2 );
2364 if ( it.key() ==
"fill"_L1 )
2365 color = QColor( it.value() );
2366 else if ( it.key() ==
"fill-opacity"_L1 )
2372 QDomElement graphicElem = graphicFillElem.firstChildElement( u
"Graphic"_s );
2373 if ( graphicElem.isNull() )
2376 QString patternName = u
"square"_s;
2377 QColor fillColor, strokeColor;
2378 double strokeWidth, size;
2379 Qt::PenStyle strokeStyle;
2380 if ( !
wellKnownMarkerFromSld( graphicElem, patternName, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
2384 if ( brushStyle == Qt::NoBrush )
2387 const QColor
c = patternName.startsWith(
"brush://"_L1 ) ? fillColor : strokeColor;
2397 const Qt::PenJoinStyle *penJoinStyle,
const Qt::PenCapStyle *penCapStyle,
2398 const QVector<qreal> *customDashPattern,
double dashOffset )
2400 QVector<qreal> dashPattern;
2401 const QVector<qreal> *pattern = &dashPattern;
2403 if ( penStyle == Qt::CustomDashLine && !customDashPattern )
2405 context.
pushWarning( QObject::tr(
"WARNING: Custom dash pattern required but not provided. Using default dash pattern." ) );
2406 penStyle = Qt::DashLine;
2418 dashPattern.push_back( 4.0 );
2419 dashPattern.push_back( 2.0 );
2422 dashPattern.push_back( 1.0 );
2423 dashPattern.push_back( 2.0 );
2425 case Qt::DashDotLine:
2426 dashPattern.push_back( 4.0 );
2427 dashPattern.push_back( 2.0 );
2428 dashPattern.push_back( 1.0 );
2429 dashPattern.push_back( 2.0 );
2431 case Qt::DashDotDotLine:
2432 dashPattern.push_back( 4.0 );
2433 dashPattern.push_back( 2.0 );
2434 dashPattern.push_back( 1.0 );
2435 dashPattern.push_back( 2.0 );
2436 dashPattern.push_back( 1.0 );
2437 dashPattern.push_back( 2.0 );
2440 case Qt::CustomDashLine:
2441 Q_ASSERT( customDashPattern );
2442 pattern = customDashPattern;
2446 context.
pushWarning( QObject::tr(
"Pen style '%1' is not supported for SLD" ).arg( penStyle ) );
2450 if ( color.isValid() )
2453 if ( color.alpha() < 255 )
2460 else if ( width == 0 )
2470 if ( !pattern->isEmpty() )
2480 Qt::PenStyle &penStyle, QColor &color,
double &width,
2481 Qt::PenJoinStyle *penJoinStyle, Qt::PenCapStyle *penCapStyle,
2482 QVector<qreal> *customDashPattern,
double *dashOffset )
2486 penStyle = Qt::SolidLine;
2487 color = QColor( 0, 0, 0 );
2490 *penJoinStyle = Qt::BevelJoin;
2492 *penCapStyle = Qt::SquareCap;
2493 if ( customDashPattern )
2494 customDashPattern->clear();
2498 if ( element.isNull() )
2500 penStyle = Qt::NoPen;
2506 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2508 QgsDebugMsgLevel( u
"found SvgParameter %1: %2"_s.arg( it.key(), it.value() ), 2 );
2510 if ( it.key() ==
"stroke"_L1 )
2512 color = QColor( it.value() );
2514 else if ( it.key() ==
"stroke-opacity"_L1 )
2518 else if ( it.key() ==
"stroke-width"_L1 )
2521 const double w = it.value().toDouble( &ok );
2525 else if ( it.key() ==
"stroke-linejoin"_L1 && penJoinStyle )
2529 else if ( it.key() ==
"stroke-linecap"_L1 && penCapStyle )
2533 else if ( it.key() ==
"stroke-dasharray"_L1 )
2536 if ( !dashPattern.isEmpty() )
2540 bool dashPatternFound =
false;
2542 if ( dashPattern.count() == 2 )
2544 if ( dashPattern.at( 0 ) == 4.0 &&
2545 dashPattern.at( 1 ) == 2.0 )
2547 penStyle = Qt::DashLine;
2548 dashPatternFound =
true;
2550 else if ( dashPattern.at( 0 ) == 1.0 &&
2551 dashPattern.at( 1 ) == 2.0 )
2553 penStyle = Qt::DotLine;
2554 dashPatternFound =
true;
2557 else if ( dashPattern.count() == 4 )
2559 if ( dashPattern.at( 0 ) == 4.0 &&
2560 dashPattern.at( 1 ) == 2.0 &&
2561 dashPattern.at( 2 ) == 1.0 &&
2562 dashPattern.at( 3 ) == 2.0 )
2564 penStyle = Qt::DashDotLine;
2565 dashPatternFound =
true;
2568 else if ( dashPattern.count() == 6 )
2570 if ( dashPattern.at( 0 ) == 4.0 &&
2571 dashPattern.at( 1 ) == 2.0 &&
2572 dashPattern.at( 2 ) == 1.0 &&
2573 dashPattern.at( 3 ) == 2.0 &&
2574 dashPattern.at( 4 ) == 1.0 &&
2575 dashPattern.at( 5 ) == 2.0 )
2577 penStyle = Qt::DashDotDotLine;
2578 dashPatternFound =
true;
2583 if ( !dashPatternFound )
2585 if ( customDashPattern )
2587 penStyle = Qt::CustomDashLine;
2588 *customDashPattern = dashPattern;
2592 QgsDebugMsgLevel( u
"custom dash pattern required but not provided. Using default dash pattern."_s, 2 );
2593 penStyle = Qt::DashLine;
2598 else if ( it.key() ==
"stroke-dashoffset"_L1 && dashOffset )
2601 const double d = it.value().toDouble( &ok );
2611 const QString &path,
const QString &mime,
2612 const QColor &color,
double size )
2614 QDomElement externalGraphicElem = doc.createElement( u
"se:ExternalGraphic"_s );
2615 element.appendChild( externalGraphicElem );
2624 QDomElement sizeElem = doc.createElement( u
"se:Size"_s );
2626 element.appendChild( sizeElem );
2631 const QString &path,
const QColor &fillColor,
double size,
const QColor &strokeColor,
double strokeWidth )
2634 parametricSvgToSld( doc, graphicElem, path, fillColor, size, strokeColor, strokeWidth, context );
2644 graphicElem.appendChild( doc.createComment( u
"Parametric SVG"_s ) );
2645 const QString parametricPath =
getSvgParametricPath( path, fillColor, strokeColor, strokeWidth );
2648 graphicElem.appendChild( doc.createComment( u
"Plain SVG fallback, no parameters"_s ) );
2651 graphicElem.appendChild( doc.createComment( u
"Well known marker fallback"_s ) );
2657 QDomElement sizeElem = doc.createElement( u
"se:Size"_s );
2659 graphicElem.appendChild( sizeElem );
2666 if ( fillColor.isValid() )
2668 url.addQueryItem( u
"fill"_s, fillColor.name() );
2669 url.addQueryItem( u
"fill-opacity"_s,
encodeSldAlpha( fillColor.alpha() ) );
2673 url.addQueryItem( u
"fill"_s, u
"#000000"_s );
2674 url.addQueryItem( u
"fill-opacity"_s, u
"1"_s );
2676 if ( strokeColor.isValid() )
2678 url.addQueryItem( u
"outline"_s, strokeColor.name() );
2679 url.addQueryItem( u
"outline-opacity"_s,
encodeSldAlpha( strokeColor.alpha() ) );
2683 url.addQueryItem( u
"outline"_s, u
"#000000"_s );
2684 url.addQueryItem( u
"outline-opacity"_s, u
"1"_s );
2686 url.addQueryItem( u
"outline-width"_s, QString::number( strokeWidth ) );
2687 const QString params = url.toString( QUrl::FullyEncoded );
2688 if ( params.isEmpty() )
2694 return basePath +
"?" + params;
2699 QString &path, QString &mime,
2700 QColor &color,
double &size )
2705 QDomElement externalGraphicElem = element.firstChildElement( u
"ExternalGraphic"_s );
2706 if ( externalGraphicElem.isNull() )
2711 const QDomElement sizeElem = element.firstChildElement( u
"Size"_s );
2712 if ( !sizeElem.isNull() )
2715 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2724 const QString &path,
const QString &format,
int *markIndex,
2725 const QColor &color,
double size )
2733 QDomElement markElem = doc.createElement( u
"se:Mark"_s );
2734 element.appendChild( markElem );
2740 QDomElement markIndexElem = doc.createElement( u
"se:MarkIndex"_s );
2741 markIndexElem.appendChild( doc.createTextNode( QString::number( *markIndex ) ) );
2742 markElem.appendChild( markIndexElem );
2746 QDomElement fillElem = doc.createElement( u
"se:Fill"_s );
2747 fillToSld( doc, fillElem, context, Qt::SolidPattern, color );
2748 markElem.appendChild( fillElem );
2753 QDomElement sizeElem = doc.createElement( u
"se:Size"_s );
2755 element.appendChild( sizeElem );
2760 QString &path, QString &format,
int &markIndex,
2761 QColor &color,
double &size )
2769 QDomElement markElem = element.firstChildElement( u
"Mark"_s );
2770 if ( markElem.isNull() )
2775 const QDomElement markIndexElem = markElem.firstChildElement( u
"MarkIndex"_s );
2776 if ( !markIndexElem.isNull() )
2779 const int i = markIndexElem.firstChild().nodeValue().toInt( &ok );
2785 QDomElement fillElem = markElem.firstChildElement( u
"Fill"_s );
2786 Qt::BrushStyle b = Qt::SolidPattern;
2791 const QDomElement sizeElem = element.firstChildElement( u
"Size"_s );
2792 if ( !sizeElem.isNull() )
2795 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2804 const QString &name,
const QColor &color,
const QColor &strokeColor, Qt::PenStyle strokeStyle,
2805 double strokeWidth,
double size )
2808 wellKnownMarkerToSld( doc, element, name, color, strokeColor, strokeStyle, context, strokeWidth, size );
2813 QDomElement markElem = doc.createElement( u
"se:Mark"_s );
2814 element.appendChild( markElem );
2816 QDomElement wellKnownNameElem = doc.createElement( u
"se:WellKnownName"_s );
2817 wellKnownNameElem.appendChild( doc.createTextNode( name ) );
2818 markElem.appendChild( wellKnownNameElem );
2821 if ( color.isValid() )
2823 QDomElement fillElem = doc.createElement( u
"se:Fill"_s );
2824 fillToSld( doc, fillElem, context, Qt::SolidPattern, color );
2825 markElem.appendChild( fillElem );
2829 if ( strokeColor.isValid() )
2831 QDomElement strokeElem = doc.createElement( u
"se:Stroke"_s );
2832 lineToSld( doc, strokeElem, strokeStyle, strokeColor, context, strokeWidth );
2833 markElem.appendChild( strokeElem );
2839 QDomElement sizeElem = doc.createElement( u
"se:Size"_s );
2841 element.appendChild( sizeElem );
2846 QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle,
2847 double &strokeWidth,
double &size )
2853 strokeColor = QColor( 0, 0, 0 );
2857 const QDomElement markElem = element.firstChildElement( u
"Mark"_s );
2858 if ( markElem.isNull() )
2861 const QDomElement wellKnownNameElem = markElem.firstChildElement( u
"WellKnownName"_s );
2862 if ( !wellKnownNameElem.isNull() )
2864 name = wellKnownNameElem.firstChild().nodeValue();
2869 QDomElement fillElem = markElem.firstChildElement( u
"Fill"_s );
2870 Qt::BrushStyle b = Qt::SolidPattern;
2875 QDomElement strokeElem = markElem.firstChildElement( u
"Stroke"_s );
2876 lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth );
2880 const QDomElement sizeElem = element.firstChildElement( u
"Size"_s );
2881 if ( !sizeElem.isNull() )
2884 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2900 if ( !rotationFunc.isEmpty() )
2902 QDomElement rotationElem = doc.createElement( u
"se:Rotation"_s );
2904 element.appendChild( rotationElem );
2910 QDomElement rotationElem = element.firstChildElement( u
"Rotation"_s );
2911 if ( !rotationElem.isNull() )
2926 if ( !alphaFunc.isEmpty() )
2928 QDomElement opacityElem = doc.createElement( u
"se:Opacity"_s );
2930 element.appendChild( opacityElem );
2936 QDomElement opacityElem = element.firstChildElement( u
"Opacity"_s );
2937 if ( !opacityElem.isNull() )
2946 if ( offset.isNull() )
2949 QDomElement displacementElem = doc.createElement( u
"se:Displacement"_s );
2950 element.appendChild( displacementElem );
2952 QDomElement dispXElem = doc.createElement( u
"se:DisplacementX"_s );
2953 dispXElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.x(), 2 ) ) );
2955 QDomElement dispYElem = doc.createElement( u
"se:DisplacementY"_s );
2956 dispYElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.y(), 2 ) ) );
2958 displacementElem.appendChild( dispXElem );
2959 displacementElem.appendChild( dispYElem );
2966 QDomElement anchorElem = doc.createElement( u
"se:AnchorPoint"_s );
2967 element.appendChild( anchorElem );
2969 QDomElement anchorXElem = doc.createElement( u
"se:AnchorPointX"_s );
2970 anchorXElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.x() ) ) );
2972 QDomElement anchorYElem = doc.createElement( u
"se:AnchorPointY"_s );
2973 anchorYElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.y() ) ) );
2975 anchorElem.appendChild( anchorXElem );
2976 anchorElem.appendChild( anchorYElem );
2981 offset = QPointF( 0, 0 );
2983 const QDomElement displacementElem = element.firstChildElement( u
"Displacement"_s );
2984 if ( displacementElem.isNull() )
2987 const QDomElement dispXElem = displacementElem.firstChildElement( u
"DisplacementX"_s );
2988 if ( !dispXElem.isNull() )
2991 const double offsetX = dispXElem.firstChild().nodeValue().toDouble( &ok );
2993 offset.setX( offsetX );
2996 const QDomElement dispYElem = displacementElem.firstChildElement( u
"DisplacementY"_s );
2997 if ( !dispYElem.isNull() )
3000 const double offsetY = dispYElem.firstChild().nodeValue().toDouble( &ok );
3002 offset.setY( offsetY );
3009 const QString &label,
const QFont &font,
3010 const QColor &color,
double size )
3013 labelTextToSld( doc, element, label, font, context, color, size );
3018 QDomElement labelElem = doc.createElement( u
"se:Label"_s );
3019 labelElem.appendChild( doc.createTextNode( label ) );
3020 element.appendChild( labelElem );
3022 QDomElement fontElem = doc.createElement( u
"se:Font"_s );
3023 element.appendChild( fontElem );
3027 fontElem.appendChild( createSldParameterElement( doc,
"font-style",
encodeSldFontStyle( font.style() ) ) );
3028 fontElem.appendChild( createSldParameterElement( doc,
"font-weight",
encodeSldFontWeight( font.weight() ) ) );
3033 if ( color.isValid() )
3035 QDomElement fillElem = doc.createElement( u
"Fill"_s );
3036 fillToSld( doc, fillElem, context, Qt::SolidPattern, color );
3037 element.appendChild( fillElem );
3042 Qt::PenJoinStyle joinStyle,
3043 Qt::PenCapStyle capStyle,
3045 const QVector<qreal> *dashPattern )
3048 penStyle.append(
"PEN(" );
3049 penStyle.append(
"c:" );
3050 penStyle.append(
c.name() );
3051 penStyle.append(
",w:" );
3053 penStyle.append( QString::number( width * mmScaleFactor ) );
3054 penStyle.append(
"mm" );
3057 if ( dashPattern && !dashPattern->isEmpty() )
3059 penStyle.append(
",p:\"" );
3060 QVector<qreal>::const_iterator pIt = dashPattern->constBegin();
3061 for ( ; pIt != dashPattern->constEnd(); ++pIt )
3063 if ( pIt != dashPattern->constBegin() )
3065 penStyle.append(
' ' );
3067 penStyle.append( QString::number( *pIt * mapUnitScaleFactor ) );
3068 penStyle.append(
'g' );
3070 penStyle.append(
'\"' );
3074 penStyle.append(
",cap:" );
3078 penStyle.append(
'p' );
3081 penStyle.append(
'r' );
3085 penStyle.append(
'b' );
3089 penStyle.append(
",j:" );
3090 switch ( joinStyle )
3093 penStyle.append(
'b' );
3096 penStyle.append(
'r' );
3100 penStyle.append(
'm' );
3106 penStyle.append(
",dp:" );
3107 penStyle.append( QString::number( offset * mapUnitScaleFactor ) );
3108 penStyle.append(
'g' );
3111 penStyle.append(
')' );
3118 brushStyle.append(
"BRUSH(" );
3119 brushStyle.append(
"fc:" );
3120 brushStyle.append( fillColor.name() );
3121 brushStyle.append(
')' );
3133 if ( geomFunc.isEmpty() )
3136 QDomElement geometryElem = doc.createElement( u
"Geometry"_s );
3137 element.appendChild( geometryElem );
3167 QDomElement geometryElem = element.firstChildElement( u
"Geometry"_s );
3168 if ( geometryElem.isNull() )
3186 context.
pushError( QObject::tr(
"Parser error encountered when converting expression to SLD: %1 - Expression was: %2" ).arg( expr.
parserErrorString(), function ) );
3190 if ( !filterElem.isNull() )
3191 element.appendChild( filterElem );
3204 if ( function ==
"ELSE"_L1 )
3207 element.appendChild( filterElem );
3216 context.
pushError( QObject::tr(
"Parser error encountered when converting expression to SLD: %1 - Expression was: %2" ).arg( expr.
parserErrorString(), function ) );
3220 if ( !filterElem.isNull() )
3221 element.appendChild( filterElem );
3229 QDomElement elem = element;
3230 if ( element.tagName() !=
"Filter"_L1 )
3232 const QDomNodeList filterNodes = element.elementsByTagName( u
"Filter"_s );
3233 if ( !filterNodes.isEmpty() )
3235 elem = filterNodes.at( 0 ).toElement();
3239 if ( elem.isNull() )
3264 const QString &path,
const QString &format )
3268 QDomElement onlineResourceElem = doc.createElement( u
"se:OnlineResource"_s );
3269 onlineResourceElem.setAttribute( u
"xlink:type"_s, u
"simple"_s );
3270 onlineResourceElem.setAttribute( u
"xlink:href"_s, url );
3271 element.appendChild( onlineResourceElem );
3273 QDomElement formatElem = doc.createElement( u
"se:Format"_s );
3274 formatElem.appendChild( doc.createTextNode( format ) );
3275 element.appendChild( formatElem );
3282 const QDomElement onlineResourceElem = element.firstChildElement( u
"OnlineResource"_s );
3283 if ( onlineResourceElem.isNull() )
3286 path = QUrl::fromPercentEncoding( onlineResourceElem.attributeNS( u
"http://www.w3.org/1999/xlink"_s, u
"href"_s ).toUtf8() );
3288 const QDomElement formatElem = element.firstChildElement( u
"Format"_s );
3289 if ( formatElem.isNull() )
3292 format = formatElem.firstChild().nodeValue();
3299 QDomElement nodeElem = doc.createElement( u
"se:SvgParameter"_s );
3300 nodeElem.setAttribute( u
"name"_s, name );
3301 nodeElem.appendChild( doc.createTextNode( value ) );
3310 QDomElement paramElem = element.firstChildElement();
3311 while ( !paramElem.isNull() )
3313 if ( paramElem.localName() ==
"SvgParameter"_L1 || paramElem.localName() ==
"CssParameter"_L1 )
3315 const QString name = paramElem.attribute( u
"name"_s );
3316 if ( paramElem.firstChild().nodeType() == QDomNode::TextNode )
3318 value = paramElem.firstChild().nodeValue();
3322 if ( paramElem.firstChild().nodeType() == QDomNode::ElementNode &&
3323 paramElem.firstChild().localName() ==
"Literal"_L1 )
3326 value = paramElem.firstChild().firstChild().nodeValue();
3330 QgsDebugError( u
"unexpected child of %1"_s.arg( paramElem.localName() ) );
3334 if ( !name.isEmpty() && !value.isEmpty() )
3335 params[ name ] = value;
3338 paramElem = paramElem.nextSiblingElement();
3346 QDomElement nodeElem = doc.createElement( u
"se:VendorOption"_s );
3347 nodeElem.setAttribute( u
"name"_s, name );
3348 nodeElem.appendChild( doc.createTextNode( value ) );
3356 QDomElement paramElem = element.firstChildElement( u
"VendorOption"_s );
3357 while ( !paramElem.isNull() )
3359 const QString name = paramElem.attribute( u
"name"_s );
3360 const QString value = paramElem.firstChild().nodeValue();
3362 if ( !name.isEmpty() && !value.isEmpty() )
3363 params[ name ] = value;
3365 paramElem = paramElem.nextSiblingElement( u
"VendorOption"_s );
3375 if ( newSymbols.userType() == QMetaType::Type::QVariantMap )
3377 return newSymbols.toMap();
3384 QDomElement e = element.firstChildElement();
3385 while ( !e.isNull() )
3387 if ( e.tagName() ==
"prop"_L1 )
3389 const QString propKey = e.attribute( u
"k"_s );
3390 const QString propValue = e.attribute( u
"v"_s );
3391 props[propKey] = propValue;
3393 e = e.nextSiblingElement();
3410 QDomElement e = element.firstChildElement();
3412 while ( !e.isNull() )
3414 if ( e.tagName() ==
"symbol"_L1 )
3418 symbols.insert( e.attribute( u
"name"_s ), symbol.release() );
3424 e = e.nextSiblingElement();
3431 QStringList subsymbols;
3433 for ( QMap<QString, QgsSymbol *>::iterator it = symbols.begin(); it != symbols.end(); ++it )
3435 if ( it.key()[0] !=
'@' )
3439 subsymbols.append( it.key() );
3441 QStringList parts = it.key().split(
'@' );
3442 if ( parts.count() < 3 )
3444 QgsDebugError(
"found subsymbol with invalid name: " + it.key() );
3448 const QString symname = parts[1];
3449 const int symlayer = parts[2].toInt();
3451 if ( !symbols.contains( symname ) )
3453 QgsDebugError(
"subsymbol references invalid symbol: " + symname );
3461 QgsDebugError(
"subsymbol references invalid symbol layer: " + QString::number( symlayer ) );
3470 QgsDebugError(
"symbol layer refused subsymbol: " + it.key() );
3477 for (
int i = 0; i < subsymbols.count(); i++ )
3478 symbols.take( subsymbols[i] );
3485 QDomElement symbolsElem = doc.createElement( tagName );
3488 for ( QMap<QString, QgsSymbol *>::iterator its = symbols.begin(); its != symbols.end(); ++its )
3490 const QDomElement symEl =
saveSymbol( its.key(), its.value(), doc, context );
3491 symbolsElem.appendChild( symEl );
3499 qDeleteAll( symbols );
3508 std::unique_ptr< QMimeData >mimeData(
new QMimeData );
3510 QDomDocument symbolDoc;
3512 symbolDoc.appendChild( symbolElem );
3513 mimeData->setText( symbolDoc.toString() );
3516 mimeData->setColorData( symbol->
color() );
3518 return mimeData.release();
3526 const QString text = data->text();
3527 if ( !text.isEmpty() )
3532 if ( doc.setContent( text ) )
3534 elem = doc.documentElement();
3536 if ( elem.nodeName() !=
"symbol"_L1 )
3537 elem = elem.firstChildElement( u
"symbol"_s );
3548 const QString rampType = element.attribute( u
"type"_s );
3573 QDomElement rampEl = doc.createElement( u
"colorramp"_s );
3574 rampEl.setAttribute( u
"type"_s, ramp->
type() );
3575 rampEl.setAttribute( u
"name"_s, name );
3583 QVariantMap rampMap;
3585 rampMap.insert( u
"type"_s, ramp->
type() );
3586 rampMap.insert( u
"name"_s, name );
3588 const QVariantMap properties = ramp->
properties();
3590 QVariantMap propertyMap;
3591 for (
auto property = properties.constBegin(); property != properties.constEnd(); ++property )
3593 propertyMap.insert( property.key(), property.value() );
3596 rampMap.insert( u
"properties"_s, propertyMap );
3602 const QVariantMap rampMap = value.toMap();
3604 const QString rampType = rampMap.value( u
"type"_s ).toString();
3607 const QVariantMap propertyMap = rampMap.value( u
"properties"_s ).toMap();
3610 for (
auto property = propertyMap.constBegin(); property != propertyMap.constEnd(); ++property )
3612 props.insert( property.key(), property.value().toString() );
3634 if ( !color.isValid() )
3641 return color.name();
3646 QList<QColor> colors;
3649 const thread_local QRegularExpression sepCommaSpaceRegExp(
"(,|\\s)" );
3650 QStringList components = colorStr.simplified().split( sepCommaSpaceRegExp );
3651 QStringList::iterator it = components.begin();
3652 for ( ; it != components.end(); ++it )
3654 const QColor result =
parseColor( *it,
true );
3655 if ( result.isValid() )
3660 if ( colors.length() > 0 )
3666 const thread_local QRegularExpression sepCommaRegExp(
"(,|\n)" );
3667 components = colorStr.split( sepCommaRegExp );
3668 it = components.begin();
3669 for ( ; it != components.end(); ++it )
3671 const QColor result =
parseColor( *it,
true );
3672 if ( result.isValid() )
3677 if ( colors.length() > 0 )
3683 components = colorStr.simplified().split( QString(
' ' ) );
3684 it = components.begin();
3685 for ( ; it != components.end(); ++it )
3687 const QColor result =
parseColor( *it,
true );
3688 if ( result.isValid() )
3693 if ( colors.length() > 0 )
3699 components = colorStr.split(
'\n' );
3700 it = components.begin();
3701 for ( ; it != components.end(); ++it )
3703 const QColor result =
parseColor( *it,
true );
3704 if ( result.isValid() )
3717 QMimeData *mimeData =
new QMimeData;
3718 mimeData->setColorData( QVariant( color ) );
3719 mimeData->setText( color.name() );
3729 if ( mimeData->hasColor() )
3731 QColor mimeColor = mimeData->colorData().value<QColor>();
3732 if ( mimeColor.isValid() )
3740 if ( mimeData->hasText() )
3744 if ( textColor.isValid() )
3762 if ( data->hasFormat( u
"text/xml"_s ) )
3765 const QByteArray encodedData = data->data( u
"text/xml"_s );
3766 QDomDocument xmlDoc;
3767 xmlDoc.setContent( encodedData );
3769 const QDomElement dragDataElem = xmlDoc.documentElement();
3770 if ( dragDataElem.tagName() ==
"ColorSchemeModelDragData"_L1 )
3772 const QDomNodeList nodeList = dragDataElem.childNodes();
3773 const int nChildNodes = nodeList.size();
3774 QDomElement currentElem;
3776 for (
int i = 0; i < nChildNodes; ++i )
3778 currentElem = nodeList.at( i ).toElement();
3779 if ( currentElem.isNull() )
3784 QPair< QColor, QString> namedColor;
3786 namedColor.second = currentElem.attribute( u
"label"_s, QString() );
3788 mimeColors << namedColor;
3793 if ( mimeColors.length() == 0 && data->hasFormat( u
"application/x-colorobject-list"_s ) )
3796 const QByteArray encodedData = data->data( u
"application/x-colorobject-list"_s );
3797 QDomDocument xmlDoc;
3798 xmlDoc.setContent( encodedData );
3800 const QDomNodeList colorsNodes = xmlDoc.elementsByTagName( u
"colors"_s );
3801 if ( colorsNodes.length() > 0 )
3803 const QDomElement colorsElem = colorsNodes.at( 0 ).toElement();
3804 const QDomNodeList colorNodeList = colorsElem.childNodes();
3805 const int nChildNodes = colorNodeList.size();
3806 QDomElement currentElem;
3808 for (
int i = 0; i < nChildNodes; ++i )
3811 currentElem = colorNodeList.at( i ).toElement();
3812 if ( currentElem.isNull() )
3817 const QDomNodeList colorNodes = currentElem.elementsByTagName( u
"color"_s );
3818 const QDomNodeList nameNodes = currentElem.elementsByTagName( u
"name"_s );
3820 if ( colorNodes.length() > 0 )
3822 const QDomElement colorElem = colorNodes.at( 0 ).toElement();
3824 const QStringList colorParts = colorElem.text().simplified().split(
' ' );
3825 if ( colorParts.length() < 3 )
3830 const int red = colorParts.at( 0 ).toDouble() * 255;
3831 const int green = colorParts.at( 1 ).toDouble() * 255;
3832 const int blue = colorParts.at( 2 ).toDouble() * 255;
3833 QPair< QColor, QString> namedColor;
3834 namedColor.first = QColor( red, green, blue );
3835 if ( nameNodes.length() > 0 )
3837 const QDomElement nameElem = nameNodes.at( 0 ).toElement();
3838 namedColor.second = nameElem.text();
3840 mimeColors << namedColor;
3846 if ( mimeColors.length() == 0 && data->hasText() )
3850 QList< QColor >::iterator it = parsedColors.begin();
3851 for ( ; it != parsedColors.end(); ++it )
3853 mimeColors << qMakePair( *it, QString() );
3857 if ( mimeColors.length() == 0 && data->hasColor() )
3860 const QColor mimeColor = data->colorData().value<QColor>();
3861 if ( mimeColor.isValid() )
3863 mimeColors << qMakePair( mimeColor, QString() );
3873 QMimeData *mimeData =
new QMimeData();
3874 QDomDocument xmlDoc;
3875 QDomElement xmlRootElement = xmlDoc.createElement( u
"ColorSchemeModelDragData"_s );
3876 xmlDoc.appendChild( xmlRootElement );
3878 QgsNamedColorList::const_iterator colorIt = colorList.constBegin();
3879 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3881 QDomElement namedColor = xmlDoc.createElement( u
"NamedColor"_s );
3883 namedColor.setAttribute( u
"label"_s, ( *colorIt ).second );
3884 xmlRootElement.appendChild( namedColor );
3886 mimeData->setData( u
"text/xml"_s, xmlDoc.toByteArray() );
3894 colorIt = colorList.constBegin();
3895 QStringList colorListString;
3896 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3898 colorListString << ( *colorIt ).first.name();
3900 mimeData->setText( colorListString.join( QLatin1Char(
'\n' ) ) );
3903 if ( colorList.length() > 0 )
3905 mimeData->setColorData( QVariant( colorList.at( 0 ).first ) );
3913 if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3918 QTextStream stream( &file );
3920 stream <<
"GIMP Palette" << Qt::endl;
3921 if ( paletteName.isEmpty() )
3923 stream <<
"Name: QGIS Palette" << Qt::endl;
3927 stream <<
"Name: " << paletteName << Qt::endl;
3929 stream <<
"Columns: 4" << Qt::endl;
3930 stream <<
'#' << Qt::endl;
3932 for ( QgsNamedColorList::ConstIterator colorIt = colors.constBegin(); colorIt != colors.constEnd(); ++colorIt )
3934 const QColor color = ( *colorIt ).first;
3935 if ( !color.isValid() )
3939 stream << u
"%1 %2 %3"_s.arg( color.red(), 3 ).arg( color.green(), 3 ).arg( color.blue(), 3 );
3940 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << Qt::endl;
3951 if ( !file.open( QIODevice::ReadOnly ) )
3954 return importedColors;
3957 QTextStream in( &file );
3959 QString line = in.readLine();
3960 if ( !line.startsWith(
"GIMP Palette"_L1 ) )
3963 return importedColors;
3967 while ( !in.atEnd() && !line.startsWith(
"Name:"_L1 ) && !line.startsWith(
'#' ) )
3969 line = in.readLine();
3971 if ( line.startsWith(
"Name:"_L1 ) )
3973 const thread_local QRegularExpression nameRx(
"Name:\\s*(\\S.*)$" );
3974 const QRegularExpressionMatch match = nameRx.match( line );
3975 if ( match.hasMatch() )
3977 name = match.captured( 1 );
3982 while ( !in.atEnd() && !line.startsWith(
'#' ) )
3984 line = in.readLine();
3989 return importedColors;
3993 const thread_local QRegularExpression rx(
"^\\s*(\\d+)\\s+(\\d+)\\s+(\\d+)(\\s.*)?$" );
3994 while ( !in.atEnd() )
3996 line = in.readLine();
3997 const QRegularExpressionMatch match = rx.match( line );
3998 if ( !match.hasMatch() )
4002 const int red = match.captured( 1 ).toInt();
4003 const int green = match.captured( 2 ).toInt();
4004 const int blue = match.captured( 3 ).toInt();
4005 const QColor color = QColor( red, green, blue );
4006 if ( !color.isValid() )
4013 if ( rx.captureCount() > 3 )
4015 label = match.captured( 4 ).simplified();
4022 importedColors << qMakePair( color, label );
4027 return importedColors;
4040 const thread_local QRegularExpression hexColorAlphaRx(
"^\\s*#?([0-9a-fA-F]{6})([0-9a-fA-F]{2})\\s*$" );
4041 QRegularExpressionMatch match = hexColorAlphaRx.match( colorStr );
4044 if ( !match.hasMatch() && QColor::isValidColor( colorStr ) )
4047 parsedColor.setNamedColor( colorStr );
4048 if ( parsedColor.isValid() )
4050 containsAlpha =
false;
4056 if ( match.hasMatch() )
4058 const QString hexColor = match.captured( 1 );
4059 parsedColor.setNamedColor( u
"#"_s + hexColor );
4061 const int alphaHex = match.captured( 2 ).toInt( &alphaOk, 16 );
4063 if ( parsedColor.isValid() && alphaOk )
4065 parsedColor.setAlpha( alphaHex );
4066 containsAlpha =
true;
4074 const thread_local QRegularExpression hexColorRx2(
"^\\s*(?:[0-9a-fA-F]{3}){1,2}\\s*$" );
4075 if ( colorStr.indexOf( hexColorRx2 ) != -1 )
4078 parsedColor.setNamedColor( u
"#"_s + colorStr );
4079 if ( parsedColor.isValid() )
4081 containsAlpha =
false;
4088 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*$" );
4089 match = rgbFormatRx.match( colorStr );
4090 if ( match.hasMatch() )
4095 const int r = match.captured( 1 ).toInt( &rOk );
4096 const int g = match.captured( 2 ).toInt( &gOk );
4097 const int b = match.captured( 3 ).toInt( &bOk );
4099 if ( !rOk || !gOk || !bOk )
4101 const float rFloat = match.captured( 1 ).toFloat();
4102 const float gFloat = match.captured( 2 ).toFloat();
4103 const float bFloat = match.captured( 3 ).toFloat();
4104 parsedColor.setRgbF( rFloat / 255.0, gFloat / 255.0, bFloat / 255.0 );
4108 parsedColor.setRgb( r, g, b );
4111 if ( parsedColor.isValid() )
4113 containsAlpha =
false;
4119 const thread_local QRegularExpression hslFormatRx(
"^\\s*hsl\\(?\\s*(\\d+(?:\\.\\d*)?)\\s*,\\s*(\\d+(?:\\.\\d*)?)\\s*%\\s*,\\s*(\\d+(?:\\.\\d*)?)\\s*%\\s*\\)?\\s*;?\\s*$" );
4120 match = hslFormatRx.match( colorStr );
4121 if ( match.hasMatch() )
4126 const int h = match.captured( 1 ).toInt( &hOk );
4127 const int s = match.captured( 2 ).toInt( &sOk );
4128 const int l = match.captured( 3 ).toInt( &lOk );
4130 if ( !hOk || !sOk || !lOk )
4132 const float hFloat = match.captured( 1 ).toFloat();
4133 const float sFloat = match.captured( 2 ).toFloat();
4134 const float lFloat = match.captured( 3 ).toFloat();
4135 parsedColor.setHslF( hFloat / 360.0, sFloat / 100.0, lFloat / 100.0 );
4139 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0 );
4141 if ( parsedColor.isValid() )
4143 containsAlpha =
false;
4149 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*$" );
4150 match = rgbPercentFormatRx.match( colorStr );
4151 if ( match.hasMatch() )
4153 const double r = match.captured( 1 ).toDouble() / 100;
4154 const double g = match.captured( 2 ).toDouble() / 100;
4155 const double b = match.captured( 3 ).toDouble() / 100;
4156 parsedColor.setRgbF( r, g, b );
4157 if ( parsedColor.isValid() )
4159 containsAlpha =
false;
4165 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*$" );
4166 match = rgbaFormatRx.match( colorStr );
4167 if ( match.hasMatch() )
4172 const int r = match.captured( 1 ).toInt( &rOk );
4173 const int g = match.captured( 2 ).toInt( &gOk );
4174 const int b = match.captured( 3 ).toInt( &bOk );
4175 const double aDouble = match.captured( 4 ).toDouble();
4177 if ( !rOk || !gOk || !bOk )
4179 const float rFloat = match.captured( 1 ).toFloat();
4180 const float gFloat = match.captured( 2 ).toFloat();
4181 const float bFloat = match.captured( 3 ).toFloat();
4182 parsedColor.setRgbF( rFloat / 255.0, gFloat / 255.0, bFloat / 255.0, aDouble );
4186 const int a =
static_cast< int >( std::round( match.captured( 4 ).toDouble() * 255.0 ) );
4187 parsedColor.setRgb( r, g, b, a );
4189 if ( parsedColor.isValid() )
4191 containsAlpha =
true;
4197 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*$" );
4198 match = rgbaPercentFormatRx.match( colorStr );
4199 if ( match.hasMatch() )
4201 const double r = match.captured( 1 ).toDouble() / 100;
4202 const double g = match.captured( 2 ).toDouble() / 100;
4203 const double b = match.captured( 3 ).toDouble() / 100;
4204 const double a = match.captured( 4 ).toDouble();
4205 parsedColor.setRgbF( r, g, b, a );
4206 if ( parsedColor.isValid() )
4208 containsAlpha =
true;
4214 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*$" );
4215 match = hslaPercentFormatRx.match( colorStr );
4216 if ( match.hasMatch() )
4221 const int h = match.captured( 1 ).toInt( &hOk );
4222 const int s = match.captured( 2 ).toInt( &sOk );
4223 const int l = match.captured( 3 ).toInt( &lOk );
4224 const double aDouble = match.captured( 4 ).toDouble();
4226 if ( !hOk || !sOk || !lOk )
4228 const float hFloat = match.captured( 1 ).toFloat();
4229 const float sFloat = match.captured( 2 ).toFloat();
4230 const float lFloat = match.captured( 3 ).toFloat();
4231 parsedColor.setHslF( hFloat / 360.0, sFloat / 100.0, lFloat / 100.0, aDouble );
4235 const int a = std::round( aDouble * 255.0 );
4236 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0, a );
4239 if ( parsedColor.isValid() )
4241 containsAlpha =
true;
4258 const QImage::Format format = image->format();
4259 if ( format != QImage::Format_ARGB32_Premultiplied && format != QImage::Format_ARGB32 )
4266 for (
int heightIndex = 0; heightIndex < image->height(); ++heightIndex )
4268 QRgb *scanLine =
reinterpret_cast< QRgb *
>( image->scanLine( heightIndex ) );
4269 for (
int widthIndex = 0; widthIndex < image->width(); ++widthIndex )
4271 myRgb = scanLine[widthIndex];
4272 if ( format == QImage::Format_ARGB32_Premultiplied )
4273 scanLine[widthIndex] = qRgba( opacity * qRed( myRgb ), opacity * qGreen( myRgb ), opacity * qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4275 scanLine[widthIndex] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4283 const int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
4284 const int alpha = ( radius < 1 ) ? 16 : ( radius > 17 ) ? 1 : tab[radius - 1];
4286 if ( image.format() != QImage::Format_ARGB32_Premultiplied
4287 && image.format() != QImage::Format_RGB32 )
4289 image = image.convertToFormat( QImage::Format_ARGB32_Premultiplied );
4292 const int r1 = rect.top();
4293 const int r2 = rect.bottom();
4294 const int c1 = rect.left();
4295 const int c2 = rect.right();
4297 const int bpl = image.bytesPerLine();
4305 i1 = i2 = ( QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3 );
4307 for (
int col = c1; col <= c2; col++ )
4309 p = image.scanLine( r1 ) + col * 4;
4310 for (
int i = i1; i <= i2; i++ )
4311 rgba[i] = p[i] << 4;
4314 for (
int j = r1; j < r2; j++, p += bpl )
4315 for (
int i = i1; i <= i2; i++ )
4316 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4319 for (
int row = r1; row <= r2; row++ )
4321 p = image.scanLine( row ) + c1 * 4;
4322 for (
int i = i1; i <= i2; i++ )
4323 rgba[i] = p[i] << 4;
4326 for (
int j = c1; j < c2; j++, p += 4 )
4327 for (
int i = i1; i <= i2; i++ )
4328 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4331 for (
int col = c1; col <= c2; col++ )
4333 p = image.scanLine( r2 ) + col * 4;
4334 for (
int i = i1; i <= i2; i++ )
4335 rgba[i] = p[i] << 4;
4338 for (
int j = r1; j < r2; j++, p -= bpl )
4339 for (
int i = i1; i <= i2; i++ )
4340 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4343 for (
int row = r1; row <= r2; row++ )
4345 p = image.scanLine( row ) + c2 * 4;
4346 for (
int i = i1; i <= i2; i++ )
4347 rgba[i] = p[i] << 4;
4350 for (
int j = c1; j < c2; j++, p -= 4 )
4351 for (
int i = i1; i <= i2; i++ )
4352 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4358 if ( alpha != 255 && alpha > 0 )
4362 const double alphaFactor = alpha / 255.;
4363 int r = 0, g = 0, b = 0;
4364 rgb.getRgb( &r, &g, &b );
4369 rgb.setRgb( r, g, b, alpha );
4371 else if ( alpha == 0 )
4373 rgb.setRgb( 0, 0, 0, 0 );
4382 if ( !simpleFill || !simpleLine )
4406 if ( simpleLine->
offset() )
4424 if ( order == Qt::AscendingOrder )
4438 const double dx = directionPoint.x() - startPoint.x();
4439 const double dy = directionPoint.y() - startPoint.y();
4440 const double length = std::sqrt( dx * dx + dy * dy );
4441 const double scaleFactor = distance / length;
4442 return QPointF( startPoint.x() + dx * scaleFactor, startPoint.y() + dy * scaleFactor );
4452 for (
int i = 0; i < svgPaths.size(); i++ )
4454 const QDir dir( svgPaths[i] );
4455 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4456 for (
const QString &item : svgSubPaths )
4458 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4461 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4462 for (
const QString &item : svgFiles )
4465 list.append( dir.path() +
'/' + item );
4477 QStringList svgPaths;
4478 svgPaths.append( directory );
4480 for (
int i = 0; i < svgPaths.size(); i++ )
4482 const QDir dir( svgPaths[i] );
4483 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4484 for (
const QString &item : svgSubPaths )
4486 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4489 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4490 for (
const QString &item : svgFiles )
4492 list.append( dir.path() +
'/' + item );
4504 if ( n.startsWith(
"base64:"_L1 ) )
4508 if ( QFileInfo::exists( n ) )
4509 return QFileInfo( n ).canonicalFilePath();
4513 if ( name.contains(
"://"_L1 ) )
4515 const QUrl url( name );
4516 if ( url.isValid() && !url.scheme().isEmpty() )
4518 if ( url.scheme().compare(
"file"_L1, Qt::CaseInsensitive ) == 0 )
4521 name = url.toLocalFile();
4522 if ( QFile( name ).exists() )
4524 return QFileInfo( name ).canonicalFilePath();
4538 for (
int i = 0; i < svgPaths.size(); i++ )
4540 QString svgPath = svgPaths[i];
4541 if ( svgPath.endsWith( QChar(
'/' ) ) )
4552 const QString myLocalPath = svgPath + QDir::separator() + name;
4555 if ( QFile( myLocalPath ).exists() )
4558 return QFileInfo( myLocalPath ).canonicalFilePath();
4562 return pathResolver.
readPath( name );
4570 if ( p.startsWith(
"base64:"_L1 ) )
4573 if ( !QFileInfo::exists( p ) )
4576 QString path = QFileInfo( p ).canonicalFilePath();
4580 bool isInSvgPaths =
false;
4581 for (
int i = 0; i < svgPaths.size(); i++ )
4583 const QString dir = QFileInfo( svgPaths[i] ).canonicalFilePath();
4585 if ( !dir.isEmpty() && path.startsWith( dir ) )
4587 path = path.mid( dir.size() + 1 );
4588 isInSvgPaths =
true;
4601 const double *srcX = line->
xData();
4602 const double *srcY = line->
yData();
4604 QPolygonF thisRes( count );
4605 QPointF *dest = thisRes.data();
4606 for (
int i = 0; i < count; ++i )
4608 *dest++ = QPointF( *srcX++, *srcY++ );
4621 const std::unique_ptr< QgsLineString > straightened( curve->
curveToLine() );
4645 points << QPointF( ( *it ).x(), ( *it ).y() );
4649 points << QPointF( 0, 0 );
4651 return QList< QList<QPolygonF> >() << ( QList< QPolygonF >() << points );
4656 QList< QList<QPolygonF> > res;
4669 QList< QList<QPolygonF> > res;
4673 QList<QPolygonF> thisPart;
4692 return QList< QList<QPolygonF> >();
4695 return QList< QList<QPolygonF> >();
4702 double cx = 0, cy = 0;
4703 double area, sum = 0;
4704 for (
int i = points.count() - 1, j = 0; j < points.count(); i = j++ )
4706 const QPointF &p1 = points[i];
4707 const QPointF &p2 = points[j];
4708 area = p1.x() * p2.y() - p1.y() * p2.x();
4710 cx += ( p1.x() + p2.x() ) * area;
4711 cy += ( p1.y() + p2.y() ) * area;
4718 if ( points.count() >= 2 )
4719 return QPointF( ( points[0].x() + points[1].x() ) / 2, ( points[0].y() + points[1].y() ) / 2 );
4720 else if ( points.count() == 1 )
4728 return QPointF( cx, cy );
4735 if ( ( rings && rings->count() > 0 ) || !
pointInPolygon( points, centroid ) )
4737 unsigned int i, pointCount = points.count();
4739 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( points[i].x(), points[i].y() );
4745 for (
auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
4747 pointCount = ( *ringIt ).count();
4749 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( ( *ringIt )[i].x(), ( *ringIt )[i].y() );
4755 if ( !pointOnSurfaceGeom.
isNull() )
4758 centroid.
setX( point.
x() );
4759 centroid.setY( point.
y() );
4764 return QPointF( centroid.x(), centroid.y() );
4769 bool inside =
false;
4771 const double x = point.x();
4772 const double y = point.y();
4774 for (
int i = 0, j = points.count() - 1; i < points.count(); i++ )
4776 const QPointF &p1 = points[i];
4777 const QPointF &p2 = points[j];
4782 if ( ( p1.y() < y && p2.y() >= y ) || ( p2.y() < y && p1.y() >= y ) )
4784 if ( p1.x() + ( y - p1.y() ) / ( p2.y() - p1.y() ) * ( p2.x() - p1.x() ) <= x )
4795 if ( polyline.size() < 2 )
4798 double totalLength = 0;
4799 auto it = polyline.begin();
4801 for ( ; it != polyline.end(); ++it )
4803 const QPointF p2 = *it;
4804 const double segmentLength = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4805 totalLength += segmentLength;
4813 if ( polyline.size() < 2 )
4816 double totalLength = 0;
4817 auto it = polyline.begin();
4819 std::vector< double > segmentLengths( polyline.size() - 1 );
4820 auto segmentLengthIt = segmentLengths.begin();
4821 for ( ; it != polyline.end(); ++it )
4823 const QPointF p2 = *it;
4824 *segmentLengthIt = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4825 totalLength += *segmentLengthIt;
4831 if ( startOffset >= 0 && totalLength <= startOffset )
4833 if ( endOffset < 0 && totalLength <= -endOffset )
4836 const double startDistance = startOffset < 0 ? totalLength + startOffset : startOffset;
4837 const double endDistance = endOffset <= 0 ? totalLength + endOffset : endOffset;
4838 QPolygonF substringPoints;
4839 substringPoints.reserve( polyline.size() );
4841 it = polyline.begin();
4842 segmentLengthIt = segmentLengths.begin();
4845 bool foundStart =
false;
4846 if (
qgsDoubleNear( startDistance, 0.0 ) || startDistance < 0 )
4848 substringPoints << p1;
4852 double distanceTraversed = 0;
4853 for ( ; it != polyline.end(); ++it )
4855 const QPointF p2 = *it;
4856 if ( distanceTraversed < startDistance && distanceTraversed + *segmentLengthIt > startDistance )
4859 const double distanceToStart = startDistance - distanceTraversed;
4860 double startX, startY;
4862 substringPoints << QPointF( startX, startY );
4865 if ( foundStart && ( distanceTraversed + *segmentLengthIt > endDistance ) )
4868 const double distanceToEnd = endDistance - distanceTraversed;
4871 if ( substringPoints.last() != QPointF( endX, endY ) )
4872 substringPoints << QPointF( endX, endY );
4874 else if ( foundStart )
4876 if ( substringPoints.last() != QPointF( p2.x(), p2.y() ) )
4877 substringPoints << QPointF( p2.x(), p2.y() );
4880 distanceTraversed += *segmentLengthIt;
4881 if ( distanceTraversed > endDistance )
4888 if ( ( substringPoints.size() < 2 ) || ( substringPoints.size() == 2 && substringPoints.at( 0 ) == substringPoints.at( 1 ) ) )
4891 return substringPoints;
4896 double vertexAngle = M_PI - ( std::atan2( p3.y() - p2.y(), p3.x() - p2.x() ) - std::atan2( p2.y() - p1.y(), p2.x() - p1.x() ) );
4900 return vertexAngle < M_PI * 135.0 / 180.0 || vertexAngle > M_PI * 225.0 / 180.0;
4905 target.reserve( target.size() + line.size() );
4906 for (
const QPointF &pt : line )
4908 if ( !target.empty() && target.last() == pt )
4917 if ( fieldOrExpression.isEmpty() )
4920 auto expr = std::make_unique< QgsExpression >( fieldOrExpression );
4921 if ( !expr->hasParserError() )
4926 Q_ASSERT( !expr->hasParserError() );
4951 QList<double> breaks;
4954 breaks.append( maximum );
4958 const int minimumCount =
static_cast< int >( classes ) / 3;
4959 const double shrink = 0.75;
4960 const double highBias = 1.5;
4961 const double adjustBias = 0.5 + 1.5 * highBias;
4962 const int divisions = classes;
4963 const double h = highBias;
4966 const double dx = maximum - minimum;
4976 cell = std::max( std::fabs( minimum ), std::fabs( maximum ) );
4977 if ( adjustBias >= 1.5 * h + 0.5 )
4979 U = 1 + ( 1.0 / ( 1 + h ) );
4983 U = 1 + ( 1.5 / ( 1 + adjustBias ) );
4985 small = dx < ( cell * U * std::max( 1, divisions ) * 1e-07 * 3.0 );
4992 cell = 9 + cell / 10;
4993 cell = cell * shrink;
4995 if ( minimumCount > 1 )
4997 cell = cell / minimumCount;
5003 if ( divisions > 1 )
5005 cell = cell / divisions;
5008 if ( cell < 20 * 1e-07 )
5013 const double base = std::pow( 10.0, std::floor( std::log10( cell ) ) );
5015 if ( ( 2 * base ) - cell < h * ( cell - unit ) )
5018 if ( ( 5 * base ) - cell < adjustBias * ( cell - unit ) )
5021 if ( ( 10.0 * base ) - cell < h * ( cell - unit ) )
5028 int start = std::floor( minimum / unit + 1e-07 );
5029 int end = std::ceil( maximum / unit - 1e-07 );
5032 while ( start * unit > minimum + ( 1e-07 * unit ) )
5036 while ( end * unit < maximum - ( 1e-07 * unit ) )
5044 int k = std::floor( 0.5 + end - start );
5045 if ( k < minimumCount )
5047 k = minimumCount - k;
5051 start = start - k / 2 + k % 2;
5055 start = start - k / 2;
5056 end = end + k / 2 + k % 2;
5059 const double minimumBreak = start * unit;
5061 const int count = end - start;
5063 breaks.reserve( count );
5064 for (
int i = 1; i < count + 1; i++ )
5066 breaks.append( minimumBreak + i * unit );
5069 if ( breaks.isEmpty() )
5072 if ( breaks.first() < minimum )
5074 breaks[0] = minimum;
5076 if ( breaks.last() > maximum )
5078 breaks[breaks.count() - 1] = maximum;
5083 if ( minimum < 0.0 && maximum > 0.0 )
5085 QList<double> breaksMinusZero;
5086 for (
int i = 0; i < breaks.count(); i++ )
5088 breaksMinusZero.append( breaks[i] - 0.0 );
5091 for (
int i = 1; i < breaks.count(); i++ )
5093 if ( std::abs( breaksMinusZero[i] ) < std::abs( breaksMinusZero[i - 1] ) )
5096 breaks[posOfMin] = 0.0;
5105 bool roundToUnit =
false;
5108 if ( props.contains( u
"uomScale"_s ) )
5111 scale = props.value( u
"uomScale"_s ).toDouble( &ok );
5120 if ( props.value( u
"uom"_s ) ==
"http://www.opengeospatial.org/se/units/metre"_L1 )
5145 scale = 1 / 0.28 * 25.4;
5169 double rescaled = size * scale;
5174 rescaled = std::round( rescaled );
5181 const double x =
rescaleUom( point.x(), unit, props );
5182 const double y =
rescaleUom( point.y(), unit, props );
5183 return QPointF( x, y );
5188 QVector<qreal> result;
5189 QVector<qreal>::const_iterator it = array.constBegin();
5190 for ( ; it != array.constEnd(); ++it )
5192 result.append(
rescaleUom( *it, unit, props ) );
5199 if ( !props.value( u
"scaleMinDenom"_s, QString() ).toString().isEmpty() )
5201 QDomElement scaleMinDenomElem = doc.createElement( u
"se:MinScaleDenominator"_s );
5202 scaleMinDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( u
"scaleMinDenom"_s ).toString().toDouble() ) ) );
5203 ruleElem.appendChild( scaleMinDenomElem );
5206 if ( !props.value( u
"scaleMaxDenom"_s, QString() ).toString().isEmpty() )
5208 QDomElement scaleMaxDenomElem = doc.createElement( u
"se:MaxScaleDenominator"_s );
5209 scaleMaxDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( u
"scaleMaxDenom"_s ).toString().toDouble() ) ) );
5210 ruleElem.appendChild( scaleMaxDenomElem );
5219 const double parentScaleMinDenom = props.value( u
"scaleMinDenom"_s, u
"0"_s ).toString().toDouble( &ok );
5220 if ( !ok || parentScaleMinDenom <= 0 )
5221 props[ u
"scaleMinDenom"_s] = QString::number( mScaleMinDenom );
5223 props[ u
"scaleMinDenom"_s] = QString::number( std::max( parentScaleMinDenom, mScaleMinDenom ) );
5229 const double parentScaleMaxDenom = props.value( u
"scaleMaxDenom"_s, u
"0"_s ).toString().toDouble( &ok );
5230 if ( !ok || parentScaleMaxDenom <= 0 )
5231 props[ u
"scaleMaxDenom"_s] = QString::number( mScaleMaxDenom );
5233 props[ u
"scaleMaxDenom"_s] = QString::number( std::min( parentScaleMaxDenom, mScaleMaxDenom ) );
5241 if ( uom ==
"http://www.opengeospatial.org/se/units/metre"_L1 )
5243 scale = 1.0 / 0.00028;
5245 else if ( uom ==
"http://www.opengeospatial.org/se/units/foot"_L1 )
5247 scale = 304.8 / 0.28;
5254 return size * scale;
5263 SymbolLayerVisitor(
const QSet<QgsSymbolLayerId> &layerIds )
5264 : mSymbolLayerIds( layerIds )
5277 void visitSymbol(
const QgsSymbol *symbol,
const QString &identifier, QVector<int> rootPath )
5281 QVector<int> indexPath = rootPath;
5282 indexPath.append( idx );
5285 if ( mSymbolLayerIds.contains(
QgsSymbolLayerId( mCurrentRuleKey + identifier, indexPath ) ) )
5287 mSymbolLayers.insert( sl );
5293 visitSymbol( subSymbol, identifier, indexPath );
5302 if ( symbolEntity->symbol() )
5304 visitSymbol( symbolEntity->symbol(), leaf.
identifier, {} );
5310 QString mCurrentRuleKey;
5311 const QSet<QgsSymbolLayerId> &mSymbolLayerIds;
5312 QSet<const QgsSymbolLayer *> mSymbolLayers;
5316 SymbolLayerVisitor visitor( symbolLayerIds );
5317 renderer->
accept( &visitor );
5318 return visitor.mSymbolLayers;
5326 SymbolRefreshRateVisitor()
5338 void visitSymbol(
const QgsSymbol *symbol )
5355 if ( refreshRate == -1 || ( animatedMarker->frameRate() > refreshRate ) )
5356 refreshRate = animatedMarker->frameRate();
5360 visitSymbol( subSymbol );
5368 if (
QgsSymbol *symbol = qgis::down_cast<const QgsStyleSymbolEntity *>( leaf.
entity )->symbol() )
5370 visitSymbol( symbol );
5376 double refreshRate = -1;
5379 SymbolRefreshRateVisitor visitor;
5380 renderer->
accept( &visitor );
5381 return visitor.refreshRate;
5386 if ( !s || !context )
5412 size = markerSymbol->
size( *context );
5414 else if ( lineSymbol )
5416 size = lineSymbol->
width( *context );
5428 if ( minSize > 0 && size < minSize )
5432 else if ( maxSize > 0 && size > maxSize )
5444 std::unique_ptr< QgsMarkerSymbol > ms( markerSymbol->
clone() );
5445 ms->setSize( size );
5451 else if ( lineSymbol )
5453 std::unique_ptr< QgsLineSymbol > ls( lineSymbol->
clone() );
5454 ls->setWidth( size );
5466 QMap<QString, QgsProperty>::const_iterator paramIt = propertiesMap.constBegin();
5467 for ( ; paramIt != propertiesMap.constEnd(); ++paramIt )
5469 properties.insert( paramIt.key(), paramIt.value().valueAsString( context ) );
5477 angleRad = std::fmod( angleRad, M_PI * 2 );
5481 angleRad += M_PI * 2;
5485 struct rationalTangent
5497 static const QList<rationalTangent> __rationalTangents
5499 { 1, 57, 0.01754206006 },
5500 { 3, 86, 0.03486958155 },
5501 { 1, 19, 0.05258306161 },
5502 { 3, 43, 0.06965457373 },
5503 { 7, 80, 0.08727771295 },
5504 { 2, 19, 0.1048769387 },
5505 { 7, 57, 0.1221951707 },
5506 { 9, 64, 0.1397088743 },
5507 { 13, 82, 0.157228051 },
5508 { 3, 17, 0.174672199 },
5509 { 7, 36, 0.1920480172 },
5510 { 17, 80, 0.209385393 },
5511 { 3, 13, 0.2267988481 },
5512 { 1, 4, 0.2449786631 },
5513 { 26, 97, 0.2618852647 },
5514 { 27, 94, 0.2797041525 },
5515 { 26, 85, 0.2968446734 },
5516 { 13, 40, 0.3142318991 },
5517 { 21, 61, 0.3315541619 },
5518 { 4, 11, 0.3487710036 },
5519 { 38, 99, 0.3664967859 },
5520 { 40, 99, 0.383984624 },
5521 { 31, 73, 0.4015805401 },
5522 { 41, 92, 0.4192323938 },
5523 { 7, 15, 0.4366271598 },
5524 { 20, 41, 0.4538440015 },
5525 { 27, 53, 0.4711662643 },
5526 { 42, 79, 0.4886424026 },
5527 { 51, 92, 0.5061751436 },
5528 { 56, 97, 0.5235757641 },
5529 { 3, 5, 0.5404195003 },
5530 { 5, 8, 0.5585993153 },
5531 { 50, 77, 0.5759185996 },
5532 { 29, 43, 0.5933501462 },
5533 { 7, 10, 0.6107259644 },
5534 { 69, 95, 0.6281701124 },
5535 { 52, 69, 0.6458159195 },
5536 { 25, 32, 0.6632029927 },
5537 { 17, 21, 0.6805212247 },
5538 { 73, 87, 0.6981204504 },
5539 { 73, 84, 0.7154487784 },
5540 { 9, 10, 0.7328151018 },
5541 { 83, 89, 0.7505285818 },
5542 { 28, 29, 0.7678561033 },
5543 { 1, 1, 0.7853981634 },
5544 { 29, 28, 0.8029402235 },
5545 { 89, 83, 0.820267745 },
5546 { 10, 9, 0.837981225 },
5547 { 107, 93, 0.855284165 },
5548 { 87, 73, 0.8726758763 },
5549 { 121, 98, 0.8900374031 },
5550 { 32, 25, 0.9075933341 },
5551 { 69, 52, 0.9249804073 },
5552 { 128, 93, 0.9424647244 },
5553 { 10, 7, 0.9600703624 },
5554 { 43, 29, 0.9774461806 },
5555 { 77, 50, 0.9948777272 },
5556 { 8, 5, 1.012197011 },
5557 { 163, 98, 1.029475114 },
5558 { 168, 97, 1.047174539 },
5559 { 175, 97, 1.064668696 },
5560 { 126, 67, 1.082075603 },
5561 { 157, 80, 1.099534652 },
5562 { 203, 99, 1.117049384 },
5563 { 193, 90, 1.134452855 },
5564 { 146, 65, 1.151936673 },
5565 { 139, 59, 1.169382787 },
5566 { 99, 40, 1.186811703 },
5567 { 211, 81, 1.204257817 },
5568 { 272, 99, 1.221730164 },
5569 { 273, 94, 1.239188479 },
5570 { 277, 90, 1.25664606 },
5571 { 157, 48, 1.274088705 },
5572 { 279, 80, 1.291550147 },
5573 { 362, 97, 1.308990773 },
5574 { 373, 93, 1.326448578 },
5575 { 420, 97, 1.343823596 },
5576 { 207, 44, 1.361353157 },
5577 { 427, 83, 1.378810994 },
5578 { 414, 73, 1.396261926 },
5579 { 322, 51, 1.413716057 },
5580 { 185, 26, 1.431170275 },
5581 { 790, 97, 1.448623034 },
5582 { 333, 35, 1.466075711 },
5583 { 1063, 93, 1.483530284 },
5584 { 1330, 93, 1.500985147 },
5585 { 706, 37, 1.518436297 },
5586 { 315, 11, 1.535889876 },
5587 { 3953, 69, 1.553343002 },
5593 static const QList<rationalTangent> rationalTangents
5595 { 1, 10, qDegreesToRadians( 5.71059 ) },
5596 { 1, 5, qDegreesToRadians( 11.3099 ) },
5597 { 1, 4, qDegreesToRadians( 14.0362 ) },
5598 { 1, 4, qDegreesToRadians( 18.4349 ) },
5599 { 1, 2, qDegreesToRadians( 26.5651 ) },
5600 { 2, 3, qDegreesToRadians( 33.6901 ) },
5601 { 1, 1, qDegreesToRadians( 45.0 ) },
5602 { 3, 2, qDegreesToRadians( 56.3099 ) },
5603 { 2, 1, qDegreesToRadians( 63.4349 ) },
5604 { 3, 1, qDegreesToRadians( 71.5651 ) },
5605 { 4, 1, qDegreesToRadians( 75.9638 ) },
5606 { 10, 1, qDegreesToRadians( 84.2894 ) },
5609 const int quadrant {
static_cast<int>( angleRad / M_PI_2 ) };
5610 Q_ASSERT( quadrant >= 0 && quadrant <= 3 );
5622 angleRad -= M_PI / 2;
5632 angleRad -= M_PI + M_PI_2;
5654 for (
int idx = 0; idx < rationalTangents.count(); ++idx )
5656 const auto item = rationalTangents.at( idx );
5657 if (
qgsDoubleNear( item.angle, angleRad, 10E-3 ) || item.angle > angleRad )
5664 const rationalTangent bTan { rationalTangents.at( rTanIdx ) };
5665 angleRad = bTan.angle;
5666 const double k { bTan.q *height *width / std::cos( angleRad ) };
5667 const int hcfH { std::gcd( bTan.p * height, bTan.q * width ) };
5668 const int hcfW { std::gcd( bTan.q * height, bTan.p * width ) };
5669 const int W1 {
static_cast<int>( std::round( k / hcfW ) ) };
5670 const int H1 {
static_cast<int>( std::round( k / hcfH ) ) };
5683 angleRad += M_PI / 2;
5696 angleRad += M_PI + M_PI_2;
5707template <
typename Functor>
5710 sl->
setId( generateId() );
5718template <
typename Functor>
5752 maskSl->clearMasks();
5755 if (
QgsSymbol *subSymbol = maskSl->subSymbol() )
5766 if ( clipGeometries.empty() )
5769 if ( bounds.isNull() )
5770 return clipGeometries;
5774 clipGeometries.erase(
5775 std::remove_if( clipGeometries.begin(), clipGeometries.end(), [&boundsRect](
const QgsGeometry & geometry )
5777 return !geometry.boundingBoxIntersects( boundsRect );
5778 } ), clipGeometries.end() );
5780 return clipGeometries;
@ PreferVector
Prefer vector-based rendering, when the result will still be visually near-identical to a raster-base...
MarkerClipMode
Marker clipping modes.
@ CompletelyWithin
Render complete markers wherever the completely fall within the polygon shape.
@ NoClipping
No clipping, render complete markers.
@ Shape
Clip to polygon shape.
@ CentroidWithin
Render complete markers wherever their centroid falls within the polygon shape.
LineClipMode
Line clipping modes.
@ NoClipping
Lines are not clipped, will extend to shape's bounding box.
@ ClipPainterOnly
Applying clipping on the painter only (i.e. line endpoints will coincide with polygon bounding box,...
@ ClipToIntersection
Clip lines to intersection with polygon shape (slower) (i.e. line endpoints will coincide with polygo...
ScaleMethod
Scale methods.
@ ScaleDiameter
Calculate scale by the diameter.
@ ScaleArea
Calculate scale by the area.
QFlags< SymbolLayerUserFlag > SymbolLayerUserFlags
Symbol layer user flags.
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
JoinStyle
Join styles for buffers.
@ Bevel
Use beveled joins.
@ Round
Use rounded joins.
@ Miter
Use mitered joins.
RenderUnit
Rendering size units.
@ Percentage
Percentage of another measurement (e.g., canvas size, feature size).
@ Millimeters
Millimeters.
@ Points
Points (e.g., for font sizes).
@ Unknown
Mixed or unknown units.
@ MetersInMapUnits
Meters value as Map units.
EndCapStyle
End cap styles for buffers.
@ Flat
Flat cap (in line with start/end of line).
@ Square
Square cap (extends past start/end of line by buffer distance).
@ RenderSymbolPreview
The render is for a symbol preview only and map based properties may not be available,...
@ Antialiasing
Use antialiasing while drawing.
@ HighQualityImageTransforms
Enable high quality image transformations, which results in better appearance of scaled or rotated ra...
VertexMarkerType
Editing vertex markers, used for showing vertices during a edit operation.
@ SemiTransparentCircle
Semi-transparent circle marker.
QFlags< SymbolRenderHint > SymbolRenderHints
Symbol render hints.
QFlags< SymbolFlag > SymbolFlags
Symbol flags.
@ RendererShouldUseSymbolLevels
If present, indicates that a QgsFeatureRenderer using the symbol should use symbol levels for best re...
@ MultiPolygon
MultiPolygon.
@ MultiLineString
MultiLineString.
SymbolCoordinateReference
Symbol coordinate reference modes.
@ Feature
Relative to feature/shape being rendered.
@ Viewport
Relative to the whole viewport/output device.
Abstract base class for all geometries.
vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry.
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
const_part_iterator const_parts_end() const
Returns STL-style iterator pointing to the imaginary const part after the last part of the geometry.
vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
const_part_iterator const_parts_begin() const
Returns STL-style iterator pointing to the const first part of the geometry.
virtual bool writeXml(QDomElement &collectionElem, const QgsPropertiesDefinition &definitions) const
Writes the current state of the property collection into an XML element.
Animated marker symbol layer class.
static QgsPaintEffectRegistry * paintEffectRegistry()
Returns the application's paint effect registry, used for managing paint effects.
static QgsSymbolLayerRegistry * symbolLayerRegistry()
Returns the application's symbol layer registry, used for managing symbol layers.
static QStringList svgPaths()
Returns the paths to svg directories.
HeadType
Possible head types.
ArrowType
Possible arrow types.
static QString typeString()
Returns the string identifier for QgsColorBrewerColorRamp.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Returns a new QgsColorBrewerColorRamp color ramp created using the properties encoded in a string map...
Abstract base class for color ramps.
virtual QColor color(double value) const =0
Returns the color corresponding to a specified value.
virtual QVariantMap properties() const =0
Returns a string map containing all the color ramp's properties.
virtual QString type() const =0
Returns a string representing the color ramp type.
static QColor colorFromString(const QString &string)
Decodes a string into a color value.
static QString colorToString(const QColor &color)
Encodes a color into a string value.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates the symbol layer.
static QString typeString()
Returns the string identifier for QgsCptCityColorRamp.
Curve polygon geometry type.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
Abstract base class for curved geometry type.
virtual QgsLineString * curveToLine(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const =0
Returns a new line string geometry corresponding to a segmentized approximation of the curve.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
bool hasFeature() const
Returns true if the context has a feature associated with it.
An expression node which takes its value from a feature's field.
Abstract base class for all nodes that can appear in an expression.
virtual QgsExpressionNode::NodeType nodeType() const =0
Gets the type of this node.
Handles parsing and evaluation of expressions (formerly called "search strings").
QString expression() const
Returns the original, unmodified expression string.
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
QString parserErrorString() const
Returns parser error.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes).
const QgsExpressionNode * rootNode() const
Returns the root node of the expression.
Abstract base class for all 2D vector feature renderers.
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
Abstract base class for fill symbol layers.
static void pointOnLineWithDistance(double x1, double y1, double x2, double y2, double distance, double &x, double &y, double *z1=nullptr, double *z2=nullptr, double *z=nullptr, double *m1=nullptr, double *m2=nullptr, double *m=nullptr)
Calculates the point a specified distance from (x1, y1) toward a second point (x2,...
static double normalizedAngle(double angle)
Ensures that an angle is in the range 0 <= angle < 2 pi.
A geometry is the spatial representation of a feature.
QgsMultiPolygonXY asMultiPolygon() const
Returns the contents of the geometry as a multi-polygon.
QgsGeometry offsetCurve(double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit) const
Returns an offset line at a given distance and side from an input line.
QgsGeometry pointOnSurface() const
Returns a point guaranteed to lie on the surface of a geometry.
static QgsGeometry fromPolylineXY(const QgsPolylineXY &polyline)
Creates a new LineString geometry from a list of QgsPointXY points.
QgsPolygonXY asPolygon() const
Returns the contents of the geometry as a polygon.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsPolylineXY asPolyline() const
Returns the contents of the geometry as a polyline.
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
Qgis::GeometryOperationResult addRing(const QVector< QgsPointXY > &ring)
Adds a new ring to this geometry.
QgsMultiPolylineXY asMultiPolyline() const
Returns the contents of the geometry as a multi-linestring.
static QgsGeometry fromPolygonXY(const QgsPolygonXY &polygon)
Creates a new geometry from a QgsPolygonXY.
QgsGeometry buffer(double distance, int segments) const
Returns a buffer region around this geometry having the given width and with a specified number of se...
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.).
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsColorRamp from a map of properties.
static QString typeString()
Returns the string identifier for QgsGradientColorRamp.
Represents a patch shape for use in map legends.
static QString typeString()
Returns the string identifier for QgsLimitedRandomColorRamp.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Returns a new QgsLimitedRandomColorRamp color ramp created using the properties encoded in a string m...
Line string geometry type, with support for z-dimension and m-values.
const double * yData() const
Returns a const pointer to the y vertex data.
const double * xData() const
Returns a const pointer to the x vertex data.
int numPoints() const override
Returns the number of points in the curve.
Abstract base class for line symbol layers.
const QgsMapUnitScale & widthMapUnitScale() const
@ AllRings
Render both exterior and interior rings.
RenderRingFilter ringFilter() const
Returns the line symbol layer's ring filter, which controls which rings are rendered when the line sy...
virtual double width() const
Returns the estimated width for the line symbol layer.
double offset() const
Returns the line's offset.
Qgis::RenderUnit widthUnit() const
Returns the units for the line's width.
A line symbol type, for rendering LineString and MultiLineString geometries.
QgsLineSymbol * clone() const override
Returns a deep copy of this symbol.
double width() const
Returns the estimated width for the whole symbol, which is the maximum width of all marker symbol lay...
Base class for all map layer types.
Struct for storing maximum and minimum scales for measurements in map units.
bool minSizeMMEnabled
Whether the minimum size in mm should be respected.
double maxScale
The maximum scale, or 0.0 if unset.
double minScale
The minimum scale, or 0.0 if unset.
double maxSizeMM
The maximum size in millimeters, or 0.0 if unset.
bool maxSizeMMEnabled
Whether the maximum size in mm should be respected.
double minSizeMM
The minimum size in millimeters, or 0.0 if unset.
A marker symbol type, for rendering Point and MultiPoint geometries.
double size() const
Returns the estimated size for the whole symbol, which is the maximum size of all marker symbol layer...
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
Special symbol layer that uses its sub symbol as a selective mask.
static QDomElement elseFilterExpression(QDomDocument &doc)
Creates an ElseFilter from doc.
static QDomElement expressionToOgcExpression(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr, bool requiresFilterElement=false)
Creates an OGC expression XML element from the exp expression with default values for the geometry na...
static QDomElement expressionToOgcFilter(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr)
Creates OGC filter XML element.
static QgsExpression * expressionFromOgcFilter(const QDomElement &element, QgsVectorLayer *layer=nullptr)
Parse XML with OGC filter into QGIS expression.
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
virtual bool saveProperties(QDomDocument &doc, QDomElement &element) const
Saves the current state of the effect to a DOM element.
Resolves relative paths into absolute paths and vice versa.
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
void setX(double x)
Sets the x value of the point.
static QString typeString()
Returns the string identifier for QgsPresetSchemeColorRamp.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Returns a new QgsPresetSchemeColorRamp color ramp created using the properties encoded in a string ma...
A grouped map of multiple QgsProperty objects, each referenced by an integer key value.
QSet< int > propertyKeys() const final
Returns a list of property keys contained within the collection.
QgsProperty property(int key) const final
Returns a matching property from the collection, if one exists.
A store for object properties.
bool isProjectColor() const
Returns true if the property is set to a linked project color.
bool isActive() const
Returns whether the property is currently active.
void setActive(bool active)
Sets whether the property is currently active.
A container for the context for various read/write operations on objects.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
A rectangle specified with double values.
Contains information about the context of a rendering operation.
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
void setDevicePixelRatio(float ratio)
Sets the device pixel ratio.
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
QgsExpressionContext & expressionContext()
Gets the expression context.
void setRasterizedRenderingPolicy(Qgis::RasterizedRenderingPolicy policy)
Sets the policy controlling when rasterisation of content during renders is permitted.
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected).
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
QVector< QgsGeometry > symbolLayerClipGeometries(const QString &symbolLayerId) const
Returns clipping geometries to be applied to the symbolLayer before rendering.
static QgsRenderContext fromQPainter(QPainter *painter)
Creates a default render context given a pixel based QPainter destination.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
A fill symbol layer which fills polygons with a repeated SVG file.
Stores properties relating to a screen.
double devicePixelRatio() const
Returns the ratio between physical pixels and device-independent pixels for the screen.
bool isValid() const
Returns true if the properties are valid.
void updateRenderContextForScreen(QgsRenderContext &context) const
Updates the settings in a render context to match the screen settings.
Renders polygons using a single fill and stroke color.
void setStrokeWidthMapUnitScale(const QgsMapUnitScale &scale)
void setStrokeWidthUnit(Qgis::RenderUnit unit)
Sets the units for the width of the fill's stroke.
void setPenJoinStyle(Qt::PenJoinStyle style)
void setStrokeWidth(double strokeWidth)
void setStrokeStyle(Qt::PenStyle strokeStyle)
void setStrokeColor(const QColor &strokeColor) override
Sets the stroke color for the symbol layer.
A simple line symbol layer, which renders lines using a line in a variety of styles (e....
bool tweakDashPatternOnCorners() const
Returns true if dash patterns tweaks should be applied on sharp corners, to ensure that a double-leng...
Qt::PenJoinStyle penJoinStyle() const
Returns the pen join style used to render the line (e.g.
double trimDistanceStart() const
Returns the trim distance for the start of the line, which dictates a length from the start of the li...
double trimDistanceEnd() const
Returns the trim distance for the end of the line, which dictates a length from the end of the line a...
bool useCustomDashPattern() const
Returns true if the line uses a custom dash pattern.
Qt::PenStyle penStyle() const
Returns the pen style used to render the line (e.g.
double dashPatternOffset() const
Returns the dash pattern offset, which dictates how far along the dash pattern the pattern should sta...
bool drawInsidePolygon() const
Returns true if the line should only be drawn inside polygons, and any portion of the line which fall...
bool alignDashPattern() const
Returns true if dash patterns should be aligned to the start and end of lines, by applying subtle twe...
Holds SLD export options and other information related to SLD export of a QGIS layer style.
void pushWarning(const QString &warning)
Pushes a warning message generated during the conversion.
void pushError(const QString &error)
Pushes a error message generated during the conversion.
virtual QgsStyle::StyleEntity type() const =0
Returns the type of style entity.
An interface for classes which can visit style entity (e.g.
@ SymbolRule
Rule based symbology or label child rule.
A symbol entity for QgsStyle databases.
bool isAnimated() const
Returns true if the symbol is animated.
double frameRate() const
Returns the symbol animation frame rate (in frames per second).
Contains settings relating to symbol buffers, which draw a "halo" effect around the symbol.
We may need stable references to symbol layers, when pointers to symbol layers are not usable (when a...
std::unique_ptr< QgsSymbolLayer > createSymbolLayerFromSld(const QString &name, QDomElement &element) const
create a new instance of symbol layer given symbol layer name and SLD
void resolvePaths(const QString &name, QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving) const
Resolve paths in properties of a particular symbol layer.
void resolveFonts(const QString &name, QVariantMap &properties, const QgsReadWriteContext &context) const
Resolve fonts from the properties of a particular symbol layer.
std::unique_ptr< QgsSymbolLayer > createSymbolLayer(const QString &name, const QVariantMap &properties=QVariantMap()) const
create a new instance of symbol layer given symbol layer name and properties
static bool externalMarkerFromSld(QDomElement &element, QString &path, QString &format, int &markIndex, QColor &color, double &size)
static QColor parseColor(const QString &colorStr, bool strictEval=false)
Attempts to parse a string as a color using a variety of common formats, including hex codes,...
static bool rotationFromSldElement(QDomElement &element, QString &rotationFunc)
static void createAnchorPointElement(QDomDocument &doc, QDomElement &element, QPointF anchor)
Creates a SE 1.1 anchor point element as a child of the specified element.
static void sortVariantList(QList< QVariant > &list, Qt::SortOrder order)
Sorts the passed list in requested order.
static Qgis::MarkerClipMode decodeMarkerClipMode(const QString &string, bool *ok=nullptr)
Decodes a string representing a marker clip mode.
static QPicture symbolLayerPreviewPicture(const QgsSymbolLayer *layer, Qgis::RenderUnit units, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::SymbolType parentSymbolType=Qgis::SymbolType::Hybrid)
Draws a symbol layer preview to a QPicture.
static bool hasExternalGraphic(QDomElement &element)
Checks if element contains an ExternalGraphic element with format "image/svg+xml".
static QString encodePenStyle(Qt::PenStyle style)
static bool needMarkerLine(QDomElement &element)
static QVector< qreal > decodeSldRealVector(const QString &s)
static bool needLinePatternFill(QDomElement &element)
static std::unique_ptr< QgsSymbol > symbolFromMimeData(const QMimeData *data)
Attempts to parse mime data as a symbol.
static void clearSymbolLayerIds(QgsSymbol *symbol)
Remove recursively unique id from all symbol symbol layers and set an empty string instead.
static QString encodeSldBrushStyle(Qt::BrushStyle style)
static Qt::PenJoinStyle decodePenJoinStyle(const QString &str)
static QgsArrowSymbolLayer::HeadType decodeArrowHeadType(const QVariant &value, bool *ok=nullptr)
Decodes a value representing an arrow head type.
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
static Q_DECL_DEPRECATED QSet< const QgsSymbolLayer * > toSymbolLayerPointers(const QgsFeatureRenderer *renderer, const QSet< QgsSymbolLayerId > &symbolLayerIds)
Converts a set of symbol layer id to a set of pointers to actual symbol layers carried by the feature...
static QVariant colorRampToVariant(const QString &name, QgsColorRamp *ramp)
Saves a color ramp to a QVariantMap, wrapped in a QVariant.
static void applyScaleDependency(QDomDocument &doc, QDomElement &ruleElem, QVariantMap &props)
Checks if the properties contain scaleMinDenom and scaleMaxDenom, if available, they are added into t...
static QgsStringMap evaluatePropertiesMap(const QMap< QString, QgsProperty > &propertiesMap, const QgsExpressionContext &context)
Evaluates a map of properties using the given context and returns a variant map with evaluated expres...
static void drawVertexMarker(double x, double y, QPainter &p, Qgis::VertexMarkerType type, int markerSize)
Draws a vertex symbol at (painter) coordinates x, y.
static Q_DECL_DEPRECATED bool createExpressionElement(QDomDocument &doc, QDomElement &element, const QString &function)
Creates a OGC Expression element based on the provided function expression.
static bool displacementFromSldElement(QDomElement &element, QPointF &offset)
static bool hasWellKnownMark(QDomElement &element)
static std::unique_ptr< QgsColorRamp > loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
static QString getSvgParametricPath(const QString &basePath, const QColor &fillColor, const QColor &strokeColor, double strokeWidth)
Encodes a reference to a parametric SVG into a path with parameters according to the SVG Parameters s...
static Q_DECL_DEPRECATED bool createFunctionElement(QDomDocument &doc, QDomElement &element, const QString &function)
Creates an OGC function element.
static std::unique_ptr< QgsSymbol > restrictedSizeSymbol(const QgsSymbol *s, double minSize, double maxSize, QgsRenderContext *context, double &width, double &height, bool *ok=nullptr)
Creates a new symbol with size restricted to min/max size if original size is out of min/max range.
static QColor decodeColor(const QString &str)
static std::unique_ptr< QgsSymbolLayer > loadSymbolLayer(QDomElement &element, const QgsReadWriteContext &context)
Reads and returns symbol layer from XML. Caller is responsible for deleting the returned object.
static bool onlineResourceFromSldElement(QDomElement &element, QString &path, QString &format)
static QPointF polygonCentroid(const QPolygonF &points)
Calculate the centroid point of a QPolygonF.
static QIcon colorRampPreviewIcon(QgsColorRamp *ramp, QSize size, int padding=0)
Returns an icon preview for a color ramp.
static QString encodeBrushStyle(Qt::BrushStyle style)
static QString svgSymbolPathToName(const QString &path, const QgsPathResolver &pathResolver)
Determines an SVG symbol's name from its path.
static bool needRasterMarker(const QDomElement &element)
Checks if element contains an ExternalGraphic element that should translate to a raster marker.
static QPixmap colorRampPreviewPixmap(QgsColorRamp *ramp, QSize size, int padding=0, Qt::Orientation direction=Qt::Horizontal, bool flipDirection=false, bool drawTransparentBackground=true)
Returns a pixmap preview for a color ramp.
static QString encodeSldAlpha(int alpha)
static void externalGraphicToSld(QDomDocument &doc, QDomElement &element, const QString &path, const QString &mime, const QColor &color, double size=-1)
static QPointF polygonPointOnSurface(const QPolygonF &points, const QVector< QPolygonF > *rings=nullptr)
Calculate a point on the surface of a QPolygonF.
static void blurImageInPlace(QImage &image, QRect rect, int radius, bool alphaOnly)
Blurs an image in place, e.g. creating Qt-independent drop shadows.
static QList< double > prettyBreaks(double minimum, double maximum, int classes)
Computes a sequence of about 'classes' equally spaced round values which cover the range of values fr...
static QPointF toPoint(const QVariant &value, bool *ok=nullptr)
Converts a value to a point.
static void premultiplyColor(QColor &rgb, int alpha)
Converts a QColor into a premultiplied ARGB QColor value using a specified alpha value.
static void saveProperties(QVariantMap props, QDomDocument &doc, QDomElement &element)
Saves the map of properties to XML.
static void multiplyImageOpacity(QImage *image, qreal opacity)
Multiplies opacity of image pixel values with a (global) transparency value.
static bool functionFromSldElement(QDomElement &element, QString &function)
static bool saveColorsToGpl(QFile &file, const QString &paletteName, const QgsNamedColorList &colors)
Exports colors to a gpl GIMP palette file.
static std::unique_ptr< QgsSymbolLayer > createFillLayerFromSld(QDomElement &element)
Creates a new fill layer from a SLD DOM element.
static QColor parseColorWithAlpha(const QString &colorStr, bool &containsAlpha, bool strictEval=false)
Attempts to parse a string as a color using a variety of common formats, including hex codes,...
static bool hasSldSymbolizer(const QDomElement &element)
Returns true if a DOM element contains an SLD Symbolizer element.
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
static QSizeF toSize(const QVariant &value, bool *ok=nullptr)
Converts a value to a size.
static double rescaleUom(double size, Qgis::RenderUnit unit, const QVariantMap &props)
Rescales the given size based on the uomScale found in the props, if any is found,...
static bool needEllipseMarker(QDomElement &element)
static std::unique_ptr< QgsSymbolLayer > createMarkerLayerFromSld(QDomElement &element)
Creates a new marker layer from a SLD DOM element.
static QgsNamedColorList colorListFromMimeData(const QMimeData *data)
Attempts to parse mime data as a list of named colors.
static void clearSymbolLayerMasks(QgsSymbol *symbol)
Remove recursively masks from all symbol symbol layers.
static bool isSharpCorner(QPointF p1, QPointF p2, QPointF p3)
Returns true if the angle formed by the line p1 - p2 - p3 forms a "sharp" corner.
static QString ogrFeatureStylePen(double width, double mmScaleFactor, double mapUnitsScaleFactor, const QColor &c, Qt::PenJoinStyle joinStyle=Qt::MiterJoin, Qt::PenCapStyle capStyle=Qt::FlatCap, double offset=0.0, const QVector< qreal > *dashPattern=nullptr)
Create ogr feature style string for pen.
static Qt::PenCapStyle decodePenCapStyle(const QString &str)
static double rendererFrameRate(const QgsFeatureRenderer *renderer)
Calculates the frame rate (in frames per second) at which the given renderer must be redrawn.
static QgsStringMap getSvgParameterList(QDomElement &element)
static bool needSvgFill(QDomElement &element)
static bool createSymbolLayerListFromSld(QDomElement &element, Qgis::GeometryType geomType, QList< QgsSymbolLayer * > &layers)
Creates a symbol layer list from a DOM element.
static bool externalGraphicFromSld(QDomElement &element, QString &path, QString &mime, QColor &color, double &size)
static Q_DECL_DEPRECATED void parametricSvgToSld(QDomDocument &doc, QDomElement &graphicElem, const QString &path, const QColor &fillColor, double size, const QColor &strokeColor, double strokeWidth)
Encodes a reference to a parametric SVG into SLD, as a succession of parametric SVG using URL paramet...
static QIcon symbolLayerPreviewIcon(const QgsSymbolLayer *layer, Qgis::RenderUnit u, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::SymbolType parentSymbolType=Qgis::SymbolType::Hybrid, QgsMapLayer *mapLayer=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Draws a symbol layer preview to an icon.
static QString encodeSldLineCapStyle(Qt::PenCapStyle style)
static QString encodeSldUom(Qgis::RenderUnit unit, double *scaleFactor)
Encodes a render unit into an SLD unit of measure string.
static QList< QList< QPolygonF > > toQPolygonF(const QgsGeometry &geometry, Qgis::SymbolType type)
Converts a geometry to a set of QPolygonF objects representing how the geometry should be drawn for a...
static std::unique_ptr< QgsSymbol > loadSymbol(const QDomElement &element, const QgsReadWriteContext &context)
Attempts to load a symbol from a DOM element.
static QVector< qreal > decodeRealVector(const QString &s)
static bool lineFromSld(QDomElement &element, Qt::PenStyle &penStyle, QColor &color, double &width, Qt::PenJoinStyle *penJoinStyle=nullptr, Qt::PenCapStyle *penCapStyle=nullptr, QVector< qreal > *customDashPattern=nullptr, double *dashOffset=nullptr)
static QPainter::CompositionMode decodeBlendMode(const QString &s)
static Qgis::ScaleMethod decodeScaleMethod(const QString &str)
Decodes a symbol scale method from a string.
static Q_DECL_DEPRECATED void createOpacityElement(QDomDocument &doc, QDomElement &element, const QString &alphaFunc)
Creates SLD opacity element.
static std::unique_ptr< QgsSymbolLayer > createLineLayerFromSld(QDomElement &element)
Creates a new line layer from a SLD DOM element.
static QString ogrFeatureStyleBrush(const QColor &fillColr)
Create ogr feature style string for brush.
static bool pointInPolygon(const QPolygonF &points, QPointF point)
Calculate whether a point is within of a QPolygonF.
static QStringList listSvgFiles()
Returns a list of all available svg files.
static QString encodeLineClipMode(Qgis::LineClipMode mode)
Encodes a line clip mode to a string.
static QPixmap symbolPreviewPixmap(const QgsSymbol *symbol, QSize size, int padding=0, QgsRenderContext *customContext=nullptr, bool selected=false, const QgsExpressionContext *expressionContext=nullptr, const QgsLegendPatchShape *shape=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Returns a pixmap preview for a color ramp.
static bool convertPolygonSymbolizerToPointMarker(QDomElement &element, QList< QgsSymbolLayer * > &layerList)
Converts a polygon symbolizer element to a list of marker symbol layers.
static Qgis::LineClipMode decodeLineClipMode(const QString &string, bool *ok=nullptr)
Decodes a string representing a line clip mode.
static bool needSvgMarker(const QDomElement &element)
Checks if element contains an ExternalGraphic element that should translate to an SVG marker.
static QStringList listSvgFilesAt(const QString &directory)
Returns a list of svg files at the specified directory.
static bool needFontMarker(QDomElement &element)
static QString encodePenCapStyle(Qt::PenCapStyle style)
static QPointF pointOnLineWithDistance(QPointF startPoint, QPointF directionPoint, double distance)
Returns a point on the line from startPoint to directionPoint that is a certain distance away from th...
static QFont::Style decodeSldFontStyle(const QString &str)
static QSize tileSize(int width, int height, double &angleRad)
Calculate the minimum size in pixels of a symbol tile given the symbol width and height and the symbo...
static QString fieldOrExpressionFromExpression(QgsExpression *expression)
Returns a field name if the whole expression is just a name of the field .
static bool opacityFromSldElement(QDomElement &element, QString &alphaFunc)
static QString encodeSldFontWeight(int weight)
static Q_DECL_DEPRECATED void externalMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &path, const QString &format, int *markIndex=nullptr, const QColor &color=QColor(), double size=-1)
Exports a marker to an SLD definition.
static QMimeData * colorListToMimeData(const QgsNamedColorList &colorList, bool allFormats=true)
Creates mime data from a list of named colors.
static Qt::BrushStyle decodeBrushStyle(const QString &str)
static QVector< QgsGeometry > collectSymbolLayerClipGeometries(const QgsRenderContext &context, const QString &symbolLayerId, const QRectF &bounds)
Returns a list of the symbol layer clip geometries to be used for the symbol layer with the specified...
static Qt::PenCapStyle decodeSldLineCapStyle(const QString &str)
static QgsNamedColorList importColorsFromGpl(QFile &file, bool &ok, QString &name)
Imports colors from a gpl GIMP palette file.
static QString encodeSize(QSizeF size)
Encodes a QSizeF to a string.
static QDomElement createVendorOptionElement(QDomDocument &doc, const QString &name, const QString &value)
static double sizeInPixelsFromSldUom(const QString &uom, double size)
Returns the size scaled in pixels according to the uom attribute.
static void appendPolyline(QPolygonF &target, const QPolygonF &line)
Appends a polyline line to an existing target polyline.
static bool wellKnownMarkerFromSld(QDomElement &element, QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle, double &strokeWidth, double &size)
Extracts properties from an SLD marker definition.
static void mergeScaleDependencies(double mScaleMinDenom, double mScaleMaxDenom, QVariantMap &props)
Merges the local scale limits, if any, with the ones already in the map, if any.
static QString colorToName(const QColor &color)
Returns a friendly display name for a color.
static int decodeSldAlpha(const QString &str)
static QString encodeSldLineJoinStyle(Qt::PenJoinStyle style)
static void createDisplacementElement(QDomDocument &doc, QDomElement &element, QPointF offset)
static QString svgSymbolNameToPath(const QString &name, const QgsPathResolver &pathResolver)
Determines an SVG symbol's path from its name.
static void drawStippledBackground(QPainter *painter, QRect rect)
static QList< QColor > parseColorList(const QString &colorStr)
Attempts to parse a string as a list of colors using a variety of common formats, including hex codes...
static QString encodeColor(const QColor &color)
static Qt::PenJoinStyle decodeSldLineJoinStyle(const QString &str)
static QVariantMap parseProperties(const QDomElement &element)
Parses the properties from XML and returns a map.
static bool fillFromSld(QDomElement &element, Qt::BrushStyle &brushStyle, QColor &color)
static Qgis::EndCapStyle penCapStyleToEndCapStyle(Qt::PenCapStyle style)
Converts a Qt pen cap style to a QGIS end cap style.
static QMimeData * symbolToMimeData(const QgsSymbol *symbol)
Creates new mime data from a symbol.
static QString encodeSldFontStyle(QFont::Style style)
static QColor colorFromMimeData(const QMimeData *data, bool &hasAlpha)
Attempts to parse mime data as a color.
static int decodeSldFontWeight(const QString &str)
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
static Q_DECL_DEPRECATED void fillToSld(QDomDocument &doc, QDomElement &element, Qt::BrushStyle brushStyle, const QColor &color=QColor())
Exports fill details to an SLD element.
static double polylineLength(const QPolygonF &polyline)
Returns the total length of a polyline.
static QDomElement saveColorRamp(const QString &name, const QgsColorRamp *ramp, QDomDocument &doc)
Encodes a color ramp's settings to an XML element.
static Qgis::RenderUnit decodeSldUom(const QString &str, double *scaleFactor=nullptr)
Decodes a SLD unit of measure string to a render unit.
static Q_DECL_DEPRECATED void createGeometryElement(QDomDocument &doc, QDomElement &element, const QString &geomFunc)
Creates an SLD geometry element.
static QgsArrowSymbolLayer::ArrowType decodeArrowType(const QVariant &value, bool *ok=nullptr)
Decodes a value representing an arrow type.
static void clearSymbolMap(QgsSymbolMap &symbols)
static Qt::BrushStyle decodeSldBrushStyle(const QString &str)
static void resetSymbolLayerIds(QgsSymbol *symbol)
Regenerate recursively unique id from all symbol symbol layers.
static double estimateMaxSymbolBleed(QgsSymbol *symbol, const QgsRenderContext &context)
Returns the maximum estimated bleed for the symbol.
static Q_DECL_DEPRECATED void wellKnownMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &name, const QColor &color, const QColor &strokeColor, Qt::PenStyle strokeStyle, double strokeWidth=-1, double size=-1)
Exports a marker to SLD.
static QString symbolProperties(QgsSymbol *symbol)
Returns a string representing the symbol.
static bool geometryFromSldElement(QDomElement &element, QString &geomFunc)
static QString encodeScaleMethod(Qgis::ScaleMethod scaleMethod)
Encodes a symbol scale method to a string.
static void createOnlineResourceElement(QDomDocument &doc, QDomElement &element, const QString &path, const QString &format)
static Qt::PenStyle decodePenStyle(const QString &str)
static Q_DECL_DEPRECATED void createRotationElement(QDomDocument &doc, QDomElement &element, const QString &rotationFunc)
Creates SLD rotation element.
static Qgis::SymbolCoordinateReference decodeCoordinateReference(const QString &string, bool *ok=nullptr)
Decodes a string representing a symbol coordinate reference mode.
static QgsSymbolMap loadSymbols(QDomElement &element, const QgsReadWriteContext &context)
Reads a collection of symbols from XML and returns them in a map. Caller is responsible for deleting ...
static QString encodePoint(QPointF point)
Encodes a QPointF to a string.
static Q_DECL_DEPRECATED void labelTextToSld(QDomDocument &doc, QDomElement &element, const QString &label, const QFont &font, const QColor &color=QColor(), double size=-1)
Exports label text to SLD.
static QDomElement saveSymbols(QgsSymbolMap &symbols, const QString &tagName, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a collection of symbols to XML with specified tagName for the top-level element.
static std::unique_ptr< QgsExpression > fieldOrExpressionToExpression(const QString &fieldOrExpression)
Returns a new valid expression instance for given field or expression string.
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
static QgsStringMap getVendorOptionList(QDomElement &element)
static Qgis::JoinStyle penJoinStyleToJoinStyle(Qt::PenJoinStyle style)
Converts a Qt pen joinstyle to a QGIS join style.
static QIcon symbolPreviewIcon(const QgsSymbol *symbol, QSize size, int padding=0, QgsLegendPatchShape *shape=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Returns an icon preview for a color ramp.
static QMimeData * colorToMimeData(const QColor &color)
Creates mime data from a color.
static bool condenseFillAndOutline(QgsFillSymbolLayer *fill, QgsLineSymbolLayer *outline)
Attempts to condense a fill and outline layer, by moving the outline layer to the fill symbol's strok...
static QPointF decodePoint(const QString &string)
Decodes a QSizeF from a string.
static QPolygonF polylineSubstring(const QPolygonF &polyline, double startOffset, double endOffset)
Returns the substring of a polyline which starts at startOffset from the beginning of the line and en...
static bool needPointPatternFill(QDomElement &element)
static QString encodeSldRealVector(const QVector< qreal > &v)
static QString encodeCoordinateReference(Qgis::SymbolCoordinateReference coordinateReference)
Encodes a symbol coordinate reference mode to a string.
static bool needRasterImageFill(QDomElement &element)
Checks if element contains a graphic fill with a raster image of type PNG, JPEG or GIF.
static QDomElement createSvgParameterElement(QDomDocument &doc, const QString &name, const QString &value)
static QString encodeMarkerClipMode(Qgis::MarkerClipMode mode)
Encodes a marker clip mode to a string.
static void lineToSld(QDomDocument &doc, QDomElement &element, Qt::PenStyle penStyle, const QColor &color, QgsSldExportContext &context, double width=-1, const Qt::PenJoinStyle *penJoinStyle=nullptr, const Qt::PenCapStyle *penCapStyle=nullptr, const QVector< qreal > *customDashPattern=nullptr, double dashOffset=0.0)
static QSizeF decodeSize(const QString &string)
Decodes a QSizeF from a string.
static bool hasExternalGraphicV2(const QDomElement &element, const QString format=QString())
Checks if element contains an ExternalGraphic element, if the optional format is specified it will al...
static QString encodeRealVector(const QVector< qreal > &v)
Abstract base class for symbol layers.
virtual QgsSymbolLayer * clone() const =0
Shall be reimplemented by subclasses to create a deep copy of the instance.
virtual bool setSubSymbol(QgsSymbol *symbol)
Sets layer's subsymbol. takes ownership of the passed symbol.
void setId(const QString &id)
Set symbol layer identifier This id has to be unique in the whole project.
bool isLocked() const
Returns true if the symbol layer colors are locked and the layer will ignore any symbol-level color c...
Property
Data definable properties.
virtual double estimateMaxBleed(const QgsRenderContext &context) const
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the layer.
virtual QVariantMap properties() const =0
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
bool enabled() const
Returns true if symbol layer is enabled and will be drawn.
virtual QString layerType() const =0
Returns a string that represents this layer type.
int renderingPass() const
Specifies the rendering pass in which this symbol layer should be rendered.
QString id() const
Returns symbol layer identifier This id is unique in the whole project.
virtual QgsSymbol * subSymbol()
Returns the symbol's sub symbol, if present.
Qgis::SymbolLayerUserFlags userFlags() const
Returns user-controlled flags which control the symbol layer's behavior.
virtual QColor color() const
Returns the "representative" color of the symbol layer.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol layer property definitions.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
virtual bool hasDataDefinedProperties() const
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
Encapsulates the context in which a symbol is being rendered.
void setOriginalGeometryType(Qgis::GeometryType type)
Sets the geometry type for the original feature geometry being rendered.
Abstract base class for all rendered symbols.
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol's property collection, used for data defined overrides.
QgsSymbolAnimationSettings & animationSettings()
Returns a reference to the symbol animation settings.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol property definitions.
Qgis::SymbolFlags flags() const
Returns flags for the symbol.
qreal opacity() const
Returns the opacity for the symbol.
bool clipFeaturesToExtent() const
Returns whether features drawn by the symbol will be clipped to the render context's extent.
QgsSymbolBufferSettings * bufferSettings()
Returns the symbol buffer settings, which control an optional "halo" effect around the symbol.
bool hasDataDefinedProperties() const
Returns whether the symbol utilizes any data defined properties.
QgsSymbolLayerList symbolLayers() const
Returns the list of symbol layers contained in the symbol.
Qgis::RenderUnit extentBufferSizeUnit() const
Returns the units for the buffer size.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
QColor color() const
Returns the symbol's color.
Qgis::SymbolType type() const
Returns the symbol's type.
double extentBuffer() const
Returns the symbol's extent buffer.
bool forceRHR() const
Returns true if polygon features drawn by the symbol will be reoriented to follow the standard right-...
static Q_INVOKABLE Qgis::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
static Qgis::GeometryType geometryType(Qgis::WkbType type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement.
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement.
QList< QPair< QColor, QString > > QgsNamedColorList
List of colors paired with a friendly display name identifying the color.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsVariantLessThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is less than the second.
bool qgsVariantGreaterThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is greater than the second.
#define Q_NOWARN_DEPRECATED_POP
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
QString qgsFlagValueToKeys(const T &value, bool *returnOk=nullptr)
Returns the value for the given keys of a flag.
T qgsFlagKeysToValue(const QString &keys, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given keys of a flag.
#define Q_NOWARN_DEPRECATED_PUSH
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
T qgsgeometry_cast(QgsAbstractGeometry *geom)
QVector< QgsPolylineXY > QgsPolygonXY
Polygon: first item of the list is outer ring, inner rings (if any) start from second item.
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)
QList< QgsSymbolLayer * > QgsSymbolLayerList
QList< QPolygonF > offsetLine(QPolygonF polyline, double dist, Qgis::GeometryType geometryType)
calculate geometry shifted by a specified distance
QPolygonF lineStringToQPolygonF(const QgsLineString *line)
QPolygonF curveToPolygonF(const QgsCurve *curve)
void changeSymbolLayerIds(QgsSymbolLayer *sl, Functor &&generateId)
QMap< QString, QgsSymbol * > QgsSymbolMap
QMap< QString, QString > QgsStringMap
Contains information relating to a node (i.e.
QString identifier
A string identifying the node.
QgsStyleEntityVisitorInterface::NodeType type
Node type.
Contains information relating to the style entity currently being visited.
const QgsStyleEntityInterface * entity
Reference to style entity being visited.
QString identifier
A string identifying the style entity.