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 )
129 return QFont::StyleNormal;
130 if ( str ==
"italic"_L1 )
131 return QFont::StyleItalic;
132 if ( str ==
"oblique"_L1 )
133 return QFont::StyleOblique;
134 return QFont::StyleNormal;
150 return QString::number( weight * 800 / 99 + 100 );
156 const int weight = str.toInt( &ok );
158 return static_cast< int >( QFont::Normal );
166 return ( weight - 100 ) * 99 / 800;
181 case Qt::DashDotLine:
182 return u
"dash dot"_s;
183 case Qt::DashDotDotLine:
184 return u
"dash dot dot"_s;
192 if ( str ==
"no"_L1 )
194 if ( str ==
"solid"_L1 )
195 return Qt::SolidLine;
196 if ( str ==
"dash"_L1 )
198 if ( str ==
"dot"_L1 )
200 if ( str ==
"dash dot"_L1 )
201 return Qt::DashDotLine;
202 if ( str ==
"dash dot dot"_L1 )
203 return Qt::DashDotDotLine;
204 return Qt::SolidLine;
224 const QString cleaned = str.toLower().trimmed();
225 if ( cleaned ==
"bevel"_L1 )
226 return Qt::BevelJoin;
227 if ( cleaned ==
"miter"_L1 )
228 return Qt::MiterJoin;
229 if ( cleaned ==
"round"_L1 )
230 return Qt::RoundJoin;
231 return Qt::BevelJoin;
251 if ( str ==
"bevel"_L1 )
252 return Qt::BevelJoin;
253 if ( str ==
"mitre"_L1 )
254 return Qt::MiterJoin;
255 if ( str ==
"round"_L1 )
256 return Qt::RoundJoin;
257 return Qt::BevelJoin;
277 if ( str ==
"square"_L1 )
278 return Qt::SquareCap;
279 if ( str ==
"flat"_L1 )
281 if ( str ==
"round"_L1 )
283 return Qt::SquareCap;
303 if ( str ==
"square"_L1 )
304 return Qt::SquareCap;
305 if ( str ==
"butt"_L1 )
307 if ( str ==
"round"_L1 )
309 return Qt::SquareCap;
316 case Qt::SolidPattern:
319 return u
"horizontal"_s;
321 return u
"vertical"_s;
322 case Qt::CrossPattern:
324 case Qt::BDiagPattern:
325 return u
"b_diagonal"_s;
326 case Qt::FDiagPattern:
327 return u
"f_diagonal"_s;
328 case Qt::DiagCrossPattern:
329 return u
"diagonal_x"_s;
330 case Qt::Dense1Pattern:
332 case Qt::Dense2Pattern:
334 case Qt::Dense3Pattern:
336 case Qt::Dense4Pattern:
338 case Qt::Dense5Pattern:
340 case Qt::Dense6Pattern:
342 case Qt::Dense7Pattern:
353 if ( str ==
"solid"_L1 )
354 return Qt::SolidPattern;
355 if ( str ==
"horizontal"_L1 )
356 return Qt::HorPattern;
357 if ( str ==
"vertical"_L1 )
358 return Qt::VerPattern;
359 if ( str ==
"cross"_L1 )
360 return Qt::CrossPattern;
361 if ( str ==
"b_diagonal"_L1 )
362 return Qt::BDiagPattern;
363 if ( str ==
"f_diagonal"_L1 )
364 return Qt::FDiagPattern;
365 if ( str ==
"diagonal_x"_L1 )
366 return Qt::DiagCrossPattern;
367 if ( str ==
"dense1"_L1 )
368 return Qt::Dense1Pattern;
369 if ( str ==
"dense2"_L1 )
370 return Qt::Dense2Pattern;
371 if ( str ==
"dense3"_L1 )
372 return Qt::Dense3Pattern;
373 if ( str ==
"dense4"_L1 )
374 return Qt::Dense4Pattern;
375 if ( str ==
"dense5"_L1 )
376 return Qt::Dense5Pattern;
377 if ( str ==
"dense6"_L1 )
378 return Qt::Dense6Pattern;
379 if ( str ==
"dense7"_L1 )
380 return Qt::Dense7Pattern;
381 if ( str ==
"no"_L1 )
383 return Qt::SolidPattern;
390 case Qt::CrossPattern:
392 case Qt::DiagCrossPattern:
403 case Qt::BDiagPattern:
405 case Qt::FDiagPattern:
406 return u
"backslash"_s;
409 case Qt::Dense1Pattern:
410 case Qt::Dense2Pattern:
411 case Qt::Dense3Pattern:
412 case Qt::Dense4Pattern:
413 case Qt::Dense5Pattern:
414 case Qt::Dense6Pattern:
415 case Qt::Dense7Pattern:
425 if ( str ==
"horline"_L1 )
426 return Qt::HorPattern;
427 if ( str ==
"line"_L1 )
428 return Qt::VerPattern;
429 if ( str ==
"cross"_L1 )
430 return Qt::CrossPattern;
431 if ( str ==
"slash"_L1 )
432 return Qt::BDiagPattern;
433 if ( str ==
"backshash"_L1 )
434 return Qt::FDiagPattern;
436 return Qt::DiagCrossPattern;
438 if ( str.startsWith(
"brush://"_L1 ) )
454 case Qt::MPenCapStyle:
467 case Qt::SvgMiterJoin:
473 case Qt::MPenJoinStyle:
482 const QDomNodeList children = element.childNodes();
483 for (
int i = 0; i < children.size(); ++i )
485 const QDomElement childElement = children.at( i ).toElement();
486 if ( childElement.tagName() ==
"se:LineSymbolizer"_L1 || childElement.tagName() ==
"se:PointSymbolizer"_L1 || childElement.tagName() ==
"se:PolygonSymbolizer"_L1 )
494 const QString compareString =
string.trimmed();
498 if ( compareString.compare(
"feature"_L1, Qt::CaseInsensitive ) == 0 )
500 else if ( compareString.compare(
"viewport"_L1, Qt::CaseInsensitive ) == 0 )
510 switch ( coordinateReference )
515 return u
"viewport"_s;
526 const QString s = value.toString().toLower().trimmed();
527 if ( s ==
"single"_L1 )
529 else if ( s ==
"reversed"_L1 )
531 else if ( s ==
"double"_L1 )
533 else if ( value.toInt() == 1 )
535 else if ( value.toInt() == 2 )
537 else if ( value.toInt( &intOk ) == 0 && intOk )
551 const QString s = value.toString().toLower().trimmed();
552 if ( s ==
"plain"_L1 )
554 else if ( s ==
"lefthalf"_L1 )
556 else if ( s ==
"righthalf"_L1 )
558 else if ( value.toInt() == 1 )
560 else if ( value.toInt() == 2 )
562 else if ( value.toInt( &intOk ) == 0 && intOk )
572 const QString compareString =
string.trimmed();
576 if ( compareString.compare(
"no"_L1, Qt::CaseInsensitive ) == 0 )
578 else if ( compareString.compare(
"shape"_L1, Qt::CaseInsensitive ) == 0 )
580 else if ( compareString.compare(
"centroid_within"_L1, Qt::CaseInsensitive ) == 0 )
582 else if ( compareString.compare(
"completely_within"_L1, Qt::CaseInsensitive ) == 0 )
599 return u
"centroid_within"_s;
601 return u
"completely_within"_s;
608 const QString compareString =
string.trimmed();
612 if ( compareString.compare(
"no"_L1, Qt::CaseInsensitive ) == 0 )
614 else if ( compareString.compare(
"during_render"_L1, Qt::CaseInsensitive ) == 0 )
616 else if ( compareString.compare(
"before_render"_L1, Qt::CaseInsensitive ) == 0 )
631 return u
"during_render"_s;
633 return u
"before_render"_s;
645 QStringList lst = str.split(
',' );
646 if ( lst.count() != 2 )
647 return QPointF( 0, 0 );
648 return QPointF( lst[0].toDouble(), lst[1].toDouble() );
659 if ( value.userType() == QMetaType::Type::QVariantList )
661 const QVariantList list = value.toList();
662 if ( list.size() != 2 )
666 bool convertOk =
false;
667 const double x = list.at( 0 ).toDouble( &convertOk );
670 const double y = list.at( 1 ).toDouble( &convertOk );
675 return QPointF( x, y );
683 const QStringList list = value.toString().trimmed().split(
',' );
684 if ( list.count() != 2 )
686 bool convertOk =
false;
687 const double x = list.at( 0 ).toDouble( &convertOk );
690 const double y = list.at( 1 ).toDouble( &convertOk );
695 return QPointF( x, y );
709 QStringList lst =
string.split(
',' );
710 if ( lst.count() != 2 )
711 return QSizeF( 0, 0 );
712 return QSizeF( lst[0].toDouble(), lst[1].toDouble() );
723 if ( value.userType() == QMetaType::Type::QVariantList )
725 const QVariantList list = value.toList();
726 if ( list.size() != 2 )
730 bool convertOk =
false;
731 const double x = list.at( 0 ).toDouble( &convertOk );
734 const double y = list.at( 1 ).toDouble( &convertOk );
739 return QSizeF( x, y );
747 const QStringList list = value.toString().trimmed().split(
',' );
748 if ( list.count() != 2 )
750 bool convertOk =
false;
751 const double x = list.at( 0 ).toDouble( &convertOk );
754 const double y = list.at( 1 ).toDouble( &convertOk );
759 return QSizeF( x, y );
779 if ( str.startsWith(
"3x:"_L1 ) )
782 const QString chopped = str.mid( 3 );
783 lst = chopped.split(
',' );
787 lst = str.split(
',' );
789 if ( lst.count() < 2 )
792 double minScale = lst[0].toDouble();
794 minScale = minScale != 0 ? 1.0 / minScale : 0;
795 double maxScale = lst[1].toDouble();
797 maxScale = maxScale != 0 ? 1.0 / maxScale : 0;
799 if ( lst.count() < 6 )
819 *scaleFactor = 0.001;
820 return u
"http://www.opengeospatial.org/se/units/metre"_s;
825 return u
"http://www.opengeospatial.org/se/units/metre"_s;
832 *scaleFactor = 1 / 0.28;
841 if ( str ==
"http://www.opengeospatial.org/se/units/metre"_L1 )
847 else if ( str ==
"http://www.opengeospatial.org/se/units/foot"_L1 )
850 *scaleFactor = 0.3048;
865 QString vectorString;
866 QVector<qreal>::const_iterator it = v.constBegin();
867 for ( ; it != v.constEnd(); ++it )
869 if ( it != v.constBegin() )
871 vectorString.append(
';' );
873 vectorString.append( QString::number( *it ) );
880 QVector<qreal> resultVector;
882 const QStringList realList = s.split(
';' );
883 QStringList::const_iterator it = realList.constBegin();
884 for ( ; it != realList.constEnd(); ++it )
886 resultVector.append( it->toDouble() );
894 QString vectorString;
895 QVector<qreal>::const_iterator it = v.constBegin();
896 for ( ; it != v.constEnd(); ++it )
898 if ( it != v.constBegin() )
900 vectorString.append(
' ' );
902 vectorString.append( QString::number( *it ) );
909 QVector<qreal> resultVector;
911 const QStringList realList = s.split(
' ' );
912 QStringList::const_iterator it = realList.constBegin();
913 for ( ; it != realList.constEnd(); ++it )
915 resultVector.append( it->toDouble() );
923 QString encodedValue;
925 switch ( scaleMethod )
928 encodedValue = u
"diameter"_s;
931 encodedValue = u
"area"_s;
941 if ( str ==
"diameter"_L1 )
955 if ( s.compare(
"Lighten"_L1, Qt::CaseInsensitive ) == 0 )
956 return QPainter::CompositionMode_Lighten;
957 if ( s.compare(
"Screen"_L1, Qt::CaseInsensitive ) == 0 )
958 return QPainter::CompositionMode_Screen;
959 if ( s.compare(
"Dodge"_L1, Qt::CaseInsensitive ) == 0 )
960 return QPainter::CompositionMode_ColorDodge;
961 if ( s.compare(
"Addition"_L1, Qt::CaseInsensitive ) == 0 )
962 return QPainter::CompositionMode_Plus;
963 if ( s.compare(
"Darken"_L1, Qt::CaseInsensitive ) == 0 )
964 return QPainter::CompositionMode_Darken;
965 if ( s.compare(
"Multiply"_L1, Qt::CaseInsensitive ) == 0 )
966 return QPainter::CompositionMode_Multiply;
967 if ( s.compare(
"Burn"_L1, Qt::CaseInsensitive ) == 0 )
968 return QPainter::CompositionMode_ColorBurn;
969 if ( s.compare(
"Overlay"_L1, Qt::CaseInsensitive ) == 0 )
970 return QPainter::CompositionMode_Overlay;
971 if ( s.compare(
"SoftLight"_L1, Qt::CaseInsensitive ) == 0 )
972 return QPainter::CompositionMode_SoftLight;
973 if ( s.compare(
"HardLight"_L1, Qt::CaseInsensitive ) == 0 )
974 return QPainter::CompositionMode_HardLight;
975 if ( s.compare(
"Difference"_L1, Qt::CaseInsensitive ) == 0 )
976 return QPainter::CompositionMode_Difference;
977 if ( s.compare(
"Subtract"_L1, Qt::CaseInsensitive ) == 0 )
978 return QPainter::CompositionMode_Exclusion;
979 return QPainter::CompositionMode_SourceOver;
984 return QIcon(
symbolPreviewPixmap( symbol, size, padding,
nullptr,
false,
nullptr, shape, screen ) );
994 QPixmap pixmap( size * devicePixelRatio );
995 pixmap.setDevicePixelRatio( devicePixelRatio );
997 pixmap.fill( Qt::transparent );
999 painter.begin( &pixmap );
1000 if ( customContext )
1004 painter.setRenderHint( QPainter::Antialiasing );
1005 painter.setRenderHint( QPainter::SmoothPixmapTransform );
1008 if ( customContext )
1015 size.setWidth( size.rwidth() - ( padding * 2 ) );
1016 size.setHeight( size.rheight() - ( padding * 2 ) );
1017 painter.translate( padding, padding );
1025 std::unique_ptr<QgsSymbol> symbol_noDD( symbol->
clone() );
1027 for (
const auto &layer : layers )
1029 for (
int i = 0; i < layer->dataDefinedProperties().count(); ++i )
1031 QgsProperty &prop = layer->dataDefinedProperties().property( i );
1037 symbol_noDD->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape, screen );
1041 std::unique_ptr<QgsSymbol> symbolClone( symbol->
clone() );
1042 symbolClone->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape, screen );
1051 double maxBleed = 0;
1056 maxBleed = layerMaxBleed > maxBleed ? layerMaxBleed : maxBleed;
1066 painter.begin( &picture );
1067 painter.setRenderHint( QPainter::Antialiasing );
1077 switch ( parentSymbolType )
1092 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
1093 layerClone->drawPreviewIcon( symbolContext, size );
1103 QPixmap pixmap( size * devicePixelRatio );
1104 pixmap.setDevicePixelRatio( devicePixelRatio );
1105 pixmap.fill( Qt::transparent );
1107 painter.begin( &pixmap );
1108 painter.setRenderHint( QPainter::Antialiasing );
1126 switch ( parentSymbolType )
1141 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
1142 layerClone->drawPreviewIcon( symbolContext, size );
1144 return QIcon( pixmap );
1154 QPixmap pixmap( size );
1155 pixmap.fill( Qt::transparent );
1158 painter.begin( &pixmap );
1161 if ( drawTransparentBackground )
1162 drawStippledBackground( &painter, QRect( padding, padding, size.width() - padding * 2, size.height() - padding * 2 ) );
1166 switch ( direction )
1168 case Qt::Horizontal:
1170 for (
int i = 0; i < size.width(); i++ )
1172 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.width() ) );
1173 painter.setPen( pen );
1174 const int x = flipDirection ? size.width() - i - 1 : i;
1175 painter.drawLine( x, 0 + padding, x, size.height() - 1 - padding );
1182 for (
int i = 0; i < size.height(); i++ )
1184 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.height() ) );
1185 painter.setPen( pen );
1186 const int y = flipDirection ? size.height() - i - 1 : i;
1187 painter.drawLine( 0 + padding, y, size.width() - 1 - padding, y );
1200 uchar pixDataRGB[] = { 255, 255, 255, 255, 127, 127, 127, 255, 127, 127, 127, 255, 255, 255, 255, 255 };
1201 const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
1203 const int width = ( rect.width() < rect.height() ) ? rect.width() / 2.5 : rect.height() / 2.5;
1204 const QPixmap pix = QPixmap::fromImage( img.scaled( width, width ) );
1207 brush.setTexture( pix );
1208 painter->fillRect( rect, brush );
1213 const qreal s = ( markerSize - 1 ) / 2.0;
1218 p.setPen( QColor( 50, 100, 120, 200 ) );
1219 p.setBrush( QColor( 200, 200, 210, 120 ) );
1220 p.drawEllipse( x - s, y - s, s * 2, s * 2 );
1223 p.setPen( QColor( 255, 0, 0 ) );
1224 p.drawLine( x - s, y + s, x + s, y - s );
1225 p.drawLine( x - s, y - s, x + s, y + s );
1237static QPolygonF makeOffsetGeometry(
const QgsPolylineXY &polyline )
1239 int i, pointCount = polyline.count();
1241 QPolygonF resultLine;
1242 resultLine.resize( pointCount );
1246 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1247 resultLine[i] = QPointF( tempPtr->
x(), tempPtr->
y() );
1251static QList<QPolygonF> makeOffsetGeometry(
const QgsPolygonXY &polygon )
1253 QList<QPolygonF> resultGeom;
1254 resultGeom.reserve( polygon.size() );
1255 for (
int ring = 0; ring < polygon.size(); ++ring )
1256 resultGeom.append( makeOffsetGeometry( polygon[ring] ) );
1262 QList<QPolygonF> resultLine;
1264 if ( polyline.count() < 2 )
1266 resultLine.append( polyline );
1270 unsigned int i, pointCount = polyline.count();
1273 QPointF *tempPtr = polyline.data();
1274 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1275 tempPolyline[i] =
QgsPointXY( tempPtr->rx(), tempPtr->ry() );
1278 if ( !tempGeometry.
isNull() )
1280 const int quadSegments = 0;
1281 const double miterLimit = 2.0;
1288 if ( !offsetGeom.
isNull() )
1290 tempGeometry = offsetGeom;
1295 resultLine.append( makeOffsetGeometry( line ) );
1300 resultLine.append( makeOffsetGeometry( tempGeometry.
asPolygon() ) );
1306 resultLine.reserve( tempMPolyline.count() );
1307 for (
int part = 0; part < tempMPolyline.count(); ++part )
1309 resultLine.append( makeOffsetGeometry( tempMPolyline[part] ) );
1316 resultLine.reserve( tempMPolygon.count() );
1317 for (
int part = 0; part < tempMPolygon.count(); ++part )
1319 resultLine.append( makeOffsetGeometry( tempMPolygon[part] ) );
1327 resultLine.append( polyline );
1336 if ( element.isNull() )
1340 QDomNode layerNode = element.firstChild();
1342 while ( !layerNode.isNull() )
1344 QDomElement e = layerNode.toElement();
1345 if ( !e.isNull() && e.tagName() !=
"data_defined_properties"_L1 && e.tagName() !=
"buffer"_L1 )
1347 if ( e.tagName() !=
"layer"_L1 )
1353 std::unique_ptr< QgsSymbolLayer > layer =
loadSymbolLayer( e, context );
1357 const QDomElement s = e.firstChildElement( u
"symbol"_s );
1360 std::unique_ptr< QgsSymbol > subSymbol(
loadSymbol( s, context ) );
1367 layers.append( layer.release() );
1369 for (
int i = 0; i < subSymbol->symbolLayerCount(); ++i )
1371 layers.append( subSymbol->symbolLayer( i )->clone() );
1376 const bool res = layer->setSubSymbol( subSymbol.release() );
1379 QgsDebugError( u
"symbol layer refused subsymbol: "_s + s.attribute(
"name" ) );
1381 layers.append( layer.release() );
1386 layers.append( layer.release() );
1391 layerNode = layerNode.nextSibling();
1394 if ( layers.isEmpty() )
1400 const QString symbolType = element.attribute( u
"type"_s );
1402 std::unique_ptr< QgsSymbol > symbol;
1403 if ( symbolType ==
"line"_L1 )
1404 symbol = std::make_unique< QgsLineSymbol >( layers );
1405 else if ( symbolType ==
"fill"_L1 )
1406 symbol = std::make_unique< QgsFillSymbol >( layers );
1407 else if ( symbolType ==
"marker"_L1 )
1408 symbol = std::make_unique< QgsMarkerSymbol >( layers );
1415 if ( element.hasAttribute( u
"outputUnit"_s ) )
1419 if ( element.hasAttribute( ( u
"mapUnitScale"_s ) ) )
1422 const double oldMin = element.attribute( u
"mapUnitMinScale"_s, u
"0.0"_s ).toDouble();
1423 mapUnitScale.
minScale = oldMin != 0 ? 1.0 / oldMin : 0;
1424 const double oldMax = element.attribute( u
"mapUnitMaxScale"_s, u
"0.0"_s ).toDouble();
1425 mapUnitScale.
maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
1426 symbol->setMapUnitScale( mapUnitScale );
1428 symbol->setOpacity( element.attribute( u
"alpha"_s, u
"1.0"_s ).toDouble() );
1429 symbol->setExtentBuffer( element.attribute( u
"extent_buffer"_s, u
"0.0"_s ).toDouble() );
1431 symbol->setClipFeaturesToExtent( element.attribute( u
"clip_to_extent"_s, u
"1"_s ).toInt() );
1432 symbol->setForceRHR( element.attribute( u
"force_rhr"_s, u
"0"_s ).toInt() );
1434 if ( element.attribute( u
"renderer_should_use_levels"_s, u
"0"_s ).toInt() )
1436 symbol->setFlags( flags );
1438 symbol->animationSettings().setIsAnimated( element.attribute( u
"is_animated"_s, u
"0"_s ).toInt() );
1439 symbol->animationSettings().setFrameRate( element.attribute( u
"frame_rate"_s, u
"10"_s ).toDouble() );
1441 if ( !element.firstChildElement( u
"buffer"_s ).isNull() )
1443 auto bufferSettings = std::make_unique< QgsSymbolBufferSettings >();
1444 bufferSettings->readXml( element, context );
1445 symbol->setBufferSettings( bufferSettings.release() );
1449 symbol->setBufferSettings(
nullptr );
1452 const QDomElement ddProps = element.firstChildElement( u
"data_defined_properties"_s );
1453 if ( !ddProps.isNull() )
1463 const QString layerClass = element.attribute( u
"class"_s );
1464 const bool locked = element.attribute( u
"locked"_s ).toInt();
1465 const bool enabled = element.attribute( u
"enabled"_s, u
"1"_s ).toInt();
1466 const int pass = element.attribute( u
"pass"_s ).toInt();
1467 const QString
id = element.attribute( u
"id"_s );
1468 const QString selectiveMaskingSetId = element.attribute( u
"selectiveMaskingSet"_s );
1482 layer->setLocked( locked );
1483 layer->setRenderingPass( pass );
1484 layer->setEnabled( enabled );
1485 layer->setUserFlags( userFlags );
1486 layer->setSelectiveMaskingSourceSetId( selectiveMaskingSetId );
1489 if ( !
id.isEmpty() )
1493 const QDomElement effectElem = element.firstChildElement( u
"effect"_s );
1494 if ( !effectElem.isNull() )
1498 layer->setPaintEffect( effect.release() );
1502 const QDomElement ddProps = element.firstChildElement( u
"data_defined_properties"_s );
1503 if ( !ddProps.isNull() )
1510 const QSet< int > oldKeys = prevProperties.
propertyKeys();
1511 for (
int key : oldKeys )
1513 if ( !layer->dataDefinedProperties().propertyKeys().contains( key ) )
1545 QDomElement symEl = doc.createElement( u
"symbol"_s );
1546 symEl.setAttribute( u
"type"_s, _nameForSymbolType( symbol->
type() ) );
1547 symEl.setAttribute( u
"name"_s, name );
1548 symEl.setAttribute( u
"alpha"_s, QString::number( symbol->
opacity() ) );
1552 symEl.setAttribute( u
"extent_buffer"_s, QString::number( symbol->
extentBuffer() ) );
1555 symEl.setAttribute( u
"force_rhr"_s, symbol->
forceRHR() ? u
"1"_s : u
"0"_s );
1557 symEl.setAttribute( u
"renderer_should_use_levels"_s, u
"1"_s );
1563 bufferSettings->writeXml( symEl, context );
1567 QDomElement ddProps = doc.createElement( u
"data_defined_properties"_s );
1569 symEl.appendChild( ddProps );
1575 QDomElement layerEl = doc.createElement( u
"layer"_s );
1576 layerEl.setAttribute( u
"class"_s, layer->
layerType() );
1577 layerEl.setAttribute( u
"enabled"_s, layer->
enabled() );
1578 layerEl.setAttribute( u
"locked"_s, layer->
isLocked() );
1580 layerEl.setAttribute( u
"id"_s, layer->
id() );
1596 QDomElement ddProps = doc.createElement( u
"data_defined_properties"_s );
1598 layerEl.appendChild( ddProps );
1602 const QString subname = u
"@%1@%2"_s.arg( name ).arg( i );
1603 const QDomElement subEl =
saveSymbol( subname, subSymbol, doc, context );
1604 layerEl.appendChild( subEl );
1606 symEl.appendChild( layerEl );
1614 QDomDocument doc( u
"qgis-symbol-definition"_s );
1617 QTextStream stream( &props );
1618 symbolElem.save( stream, -1 );
1626 if ( element.isNull() )
1629 const QString symbolizerName = element.localName();
1631 if ( symbolizerName ==
"PointSymbolizer"_L1 )
1634 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1635 if ( graphicElem.isNull() )
1637 QgsDebugError( u
"Graphic element not found in PointSymbolizer"_s );
1648 layers.append( l.release() );
1658 layers.append( l.release() );
1668 layers.append( l.release() );
1680 if ( symbolizerName ==
"LineSymbolizer"_L1 )
1683 const QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
1684 if ( strokeElem.isNull() )
1686 QgsDebugError( u
"Stroke element not found in LineSymbolizer"_s );
1699 layers.append( l.release() );
1709 layers.append( l.release() );
1721 if ( symbolizerName ==
"PolygonSymbolizer"_L1 )
1724 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
1725 const QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
1726 if ( fillElem.isNull() && strokeElem.isNull() )
1728 QgsDebugError( u
"neither Fill nor Stroke element not found in PolygonSymbolizer"_s );
1742 layers.append( l.release() );
1746 if ( lastLayer->
layerType() ==
"SimpleFill"_L1 || lastLayer->
layerType() ==
"SVGFill"_L1 )
1754 layers.append( l.release() );
1764 layers.append( l.release() );
1787 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
1788 if ( fillElem.isNull() )
1794 std::unique_ptr< QgsSymbolLayer > l;
1812 const QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
1813 if ( strokeElem.isNull() )
1819 std::unique_ptr< QgsSymbolLayer > l;
1831 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1832 if ( graphicElem.isNull() )
1838 std::unique_ptr< QgsSymbolLayer > l;
1861 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1862 if ( graphicElem.isNull() )
1865 const QDomElement externalGraphicElem = graphicElem.firstChildElement( u
"ExternalGraphic"_s );
1866 if ( externalGraphicElem.isNull() )
1870 const QDomElement formatElem = externalGraphicElem.firstChildElement( u
"Format"_s );
1871 if ( formatElem.isNull() )
1874 const QString elementFormat = formatElem.firstChild().nodeValue();
1875 if ( !format.isEmpty() && elementFormat != format )
1877 QgsDebugMsgLevel(
"unsupported External Graphic format found: " + elementFormat, 4 );
1882 const QDomElement onlineResourceElem = externalGraphicElem.firstChildElement( u
"OnlineResource"_s );
1883 const QDomElement inlineContentElem = externalGraphicElem.firstChildElement( u
"InlineContent"_s );
1885 if ( !onlineResourceElem.isNull() )
1889 else if ( !inlineContentElem.isNull() )
1902 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1903 if ( graphicElem.isNull() )
1906 const QDomElement markElem = graphicElem.firstChildElement( u
"Mark"_s );
1907 if ( markElem.isNull() )
1910 const QDomElement wellKnownNameElem = markElem.firstChildElement( u
"WellKnownName"_s );
1911 return !wellKnownNameElem.isNull();
1917 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1918 if ( graphicElem.isNull() )
1921 const QDomElement markElem = graphicElem.firstChildElement( u
"Mark"_s );
1922 if ( markElem.isNull() )
1926 const QDomElement formatElem = markElem.firstChildElement( u
"Format"_s );
1927 if ( formatElem.isNull() )
1930 const QString format = formatElem.firstChild().nodeValue();
1931 if ( format !=
"ttf"_L1 )
1933 QgsDebugError(
"unsupported Graphic Mark format found: " + format );
1938 const QDomElement onlineResourceElem = markElem.firstChildElement( u
"OnlineResource"_s );
1939 const QDomElement inlineContentElem = markElem.firstChildElement( u
"InlineContent"_s );
1940 if ( !onlineResourceElem.isNull() )
1943 const QDomElement markIndexElem = markElem.firstChildElement( u
"MarkIndex"_s );
1944 if ( !markIndexElem.isNull() )
1947 else if ( !inlineContentElem.isNull() )
1968 QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1969 if ( graphicElem.isNull() )
1973 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
1975 if ( it.key() ==
"widthHeightFactor"_L1 )
1986 const QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
1987 if ( strokeElem.isNull() )
1990 QDomElement graphicStrokeElem = strokeElem.firstChildElement( u
"GraphicStroke"_s );
1991 if ( graphicStrokeElem.isNull() )
1999 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
2000 if ( fillElem.isNull() )
2003 const QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
2004 if ( graphicFillElem.isNull() )
2007 QDomElement graphicElem = graphicFillElem.firstChildElement( u
"Graphic"_s );
2008 if ( graphicElem.isNull() )
2014 QColor fillColor, strokeColor;
2015 double size, strokeWidth;
2016 Qt::PenStyle strokeStyle;
2017 if ( !
wellKnownMarkerFromSld( graphicElem, name, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
2020 if ( name !=
"horline"_L1 )
2028 const double angle = angleFunc.toDouble( &ok );
2034 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
2035 if ( fillElem.isNull() )
2038 const QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
2039 if ( graphicFillElem.isNull() )
2042 const QDomElement graphicElem = graphicFillElem.firstChildElement( u
"Graphic"_s );
2043 if ( graphicElem.isNull() )
2046 const QDomElement markElem = graphicElem.firstChildElement( u
"Mark"_s );
2047 if ( markElem.isNull() )
2055 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
2056 if ( fillElem.isNull() )
2059 QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
2060 if ( graphicFillElem.isNull() )
2068 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
2069 if ( fillElem.isNull() )
2072 QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
2073 if ( graphicFillElem.isNull() )
2093 QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
2094 QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
2098 bool validFill =
false, validStroke =
false;
2103 Qt::BrushStyle fillStyle;
2105 if (
fillFromSld( fillElem, fillStyle, fillColor ) )
2111 Qt::PenStyle strokeStyle;
2112 double strokeWidth = 1.0, dashOffset = 0.0;
2113 QVector<qreal> customDashPattern;
2115 if (
lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth,
nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2118 if ( validFill || validStroke )
2121 map[u
"name"_s] = u
"square"_s;
2124 map[u
"size"_s] = QString::number( 6 );
2125 map[u
"angle"_s] = QString::number( 0 );
2126 map[u
"offset"_s] =
encodePoint( QPointF( 0, 0 ) );
2133 bool validFill =
false, validStroke =
false;
2136 QString name, format;
2138 QColor fillColor, strokeColor;
2139 double strokeWidth = 1.0, size = 0.0, angle = 0.0;
2143 const QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
2144 if ( !graphicFillElem.isNull() )
2147 QDomElement graphicElem = graphicFillElem.firstChildElement( u
"Graphic"_s );
2148 if ( !graphicElem.isNull() )
2154 const QDomElement graphicChildElem = graphicElem.firstChildElement();
2155 while ( !graphicChildElem.isNull() )
2157 if ( graphicChildElem.localName() ==
"Mark"_L1 )
2160 const QDomElement wellKnownNameElem = graphicChildElem.firstChildElement( u
"WellKnownName"_s );
2161 if ( !wellKnownNameElem.isNull() )
2163 name = wellKnownNameElem.firstChild().nodeValue();
2169 if ( graphicChildElem.localName() ==
"ExternalGraphic"_L1 || graphicChildElem.localName() ==
"Mark"_L1 )
2172 const QDomElement formatElem = graphicChildElem.firstChildElement( u
"Format"_s );
2173 if ( formatElem.isNull() )
2176 format = formatElem.firstChild().nodeValue();
2180 if ( graphicChildElem.localName() ==
"ExternalGraphic"_L1 && format !=
"image/svg+xml"_L1 )
2185 if ( graphicChildElem.localName() ==
"Mark"_L1 && format !=
"ttf"_L1 )
2189 const QDomElement onlineResourceElem = graphicChildElem.firstChildElement( u
"OnlineResource"_s );
2190 const QDomElement inlineContentElem = graphicChildElem.firstChildElement( u
"InlineContent"_s );
2192 if ( !onlineResourceElem.isNull() )
2194 name = onlineResourceElem.attributeNS( u
"http://www.w3.org/1999/xlink"_s, u
"href"_s );
2196 if ( graphicChildElem.localName() ==
"Mark"_L1 && format ==
"ttf"_L1 )
2199 if ( name.startsWith(
"ttf://"_L1 ) )
2200 name = name.mid( 6 );
2203 const QDomElement markIndexElem = graphicChildElem.firstChildElement( u
"MarkIndex"_s );
2204 if ( markIndexElem.isNull() )
2208 const int v = markIndexElem.firstChild().nodeValue().toInt( &ok );
2219 else if ( !inlineContentElem.isNull() )
2229 if ( graphicChildElem.localName() ==
"Mark"_L1 )
2238 if ( found && graphicChildElem.localName() ==
"Mark"_L1 )
2245 Qt::BrushStyle markFillStyle;
2247 QDomElement markFillElem = graphicChildElem.firstChildElement( u
"Fill"_s );
2248 if (
fillFromSld( markFillElem, markFillStyle, fillColor ) )
2253 Qt::PenStyle strokeStyle;
2254 double strokeWidth = 1.0, dashOffset = 0.0;
2255 QVector<qreal> customDashPattern;
2257 QDomElement markStrokeElem = graphicChildElem.firstChildElement( u
"Stroke"_s );
2258 if (
lineFromSld( markStrokeElem, strokeStyle, strokeColor, strokeWidth,
nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2265 const QDomElement opacityElem = graphicElem.firstChildElement( u
"Opacity"_s );
2266 if ( !opacityElem.isNull() )
2267 fillColor.setAlpha(
decodeSldAlpha( opacityElem.firstChild().nodeValue() ) );
2269 const QDomElement sizeElem = graphicElem.firstChildElement( u
"Size"_s );
2270 if ( !sizeElem.isNull() )
2273 const double v = sizeElem.firstChild().nodeValue().toDouble( &ok );
2282 const double v = angleFunc.toDouble( &ok );
2292 if ( validFill || validStroke )
2294 if ( format ==
"image/svg+xml"_L1 )
2297 map[u
"name"_s] = name;
2298 map[u
"fill"_s] = fillColor.name();
2299 map[u
"outline"_s] = strokeColor.name();
2300 map[u
"outline-width"_s] = QString::number( strokeWidth );
2302 map[u
"size"_s] = QString::number( size );
2304 map[u
"angle"_s] = QString::number( angle );
2305 if ( !offset.isNull() )
2309 else if ( format ==
"ttf"_L1 )
2312 map[u
"font"_s] = name;
2313 map[u
"chr"_s] = markIndex;
2316 map[u
"size"_s] = QString::number( size );
2318 map[u
"angle"_s] = QString::number( angle );
2319 if ( !offset.isNull() )
2326 if ( layers.isEmpty() )
2329 layerList << layers;
2337 fillToSld( doc, element, context, brushStyle, color );
2342 QString patternName;
2343 switch ( brushStyle )
2348 case Qt::SolidPattern:
2349 if ( color.isValid() )
2352 if ( color.alpha() < 255 )
2357 case Qt::CrossPattern:
2358 case Qt::DiagCrossPattern:
2359 case Qt::HorPattern:
2360 case Qt::VerPattern:
2361 case Qt::BDiagPattern:
2362 case Qt::FDiagPattern:
2363 case Qt::Dense1Pattern:
2364 case Qt::Dense2Pattern:
2365 case Qt::Dense3Pattern:
2366 case Qt::Dense4Pattern:
2367 case Qt::Dense5Pattern:
2368 case Qt::Dense6Pattern:
2369 case Qt::Dense7Pattern:
2374 context.
pushWarning( QObject::tr(
"Brush style '%1' is not supported for SLD" ).arg( brushStyle ) );
2378 QDomElement graphicFillElem = doc.createElement( u
"se:GraphicFill"_s );
2379 element.appendChild( graphicFillElem );
2381 QDomElement graphicElem = doc.createElement( u
"se:Graphic"_s );
2382 graphicFillElem.appendChild( graphicElem );
2384 const QColor fillColor = patternName.startsWith(
"brush://"_L1 ) ? color : QColor();
2385 const QColor strokeColor = !patternName.startsWith(
"brush://"_L1 ) ? color : QColor();
2388 wellKnownMarkerToSld( doc, graphicElem, patternName, fillColor, strokeColor, Qt::SolidLine, context, -1, -1 );
2395 brushStyle = Qt::SolidPattern;
2396 color = QColor( 128, 128, 128 );
2398 if ( element.isNull() )
2400 brushStyle = Qt::NoBrush;
2405 const QDomElement graphicFillElem = element.firstChildElement( u
"GraphicFill"_s );
2407 if ( graphicFillElem.isNull() )
2410 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2412 QgsDebugMsgLevel( u
"found SvgParameter %1: %2"_s.arg( it.key(), it.value() ), 2 );
2414 if ( it.key() ==
"fill"_L1 )
2415 color = QColor( it.value() );
2416 else if ( it.key() ==
"fill-opacity"_L1 )
2422 QDomElement graphicElem = graphicFillElem.firstChildElement( u
"Graphic"_s );
2423 if ( graphicElem.isNull() )
2426 QString patternName = u
"square"_s;
2427 QColor fillColor, strokeColor;
2428 double strokeWidth, size;
2429 Qt::PenStyle strokeStyle;
2430 if ( !
wellKnownMarkerFromSld( graphicElem, patternName, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
2434 if ( brushStyle == Qt::NoBrush )
2437 const QColor
c = patternName.startsWith(
"brush://"_L1 ) ? fillColor : strokeColor;
2447 QDomElement &element,
2448 Qt::PenStyle penStyle,
2449 const QColor &color,
2452 const Qt::PenJoinStyle *penJoinStyle,
2453 const Qt::PenCapStyle *penCapStyle,
2454 const QVector<qreal> *customDashPattern,
2458 QVector<qreal> dashPattern;
2459 const QVector<qreal> *pattern = &dashPattern;
2461 if ( penStyle == Qt::CustomDashLine && !customDashPattern )
2463 context.
pushWarning( QObject::tr(
"WARNING: Custom dash pattern required but not provided. Using default dash pattern." ) );
2464 penStyle = Qt::DashLine;
2476 dashPattern.push_back( 4.0 );
2477 dashPattern.push_back( 2.0 );
2480 dashPattern.push_back( 1.0 );
2481 dashPattern.push_back( 2.0 );
2483 case Qt::DashDotLine:
2484 dashPattern.push_back( 4.0 );
2485 dashPattern.push_back( 2.0 );
2486 dashPattern.push_back( 1.0 );
2487 dashPattern.push_back( 2.0 );
2489 case Qt::DashDotDotLine:
2490 dashPattern.push_back( 4.0 );
2491 dashPattern.push_back( 2.0 );
2492 dashPattern.push_back( 1.0 );
2493 dashPattern.push_back( 2.0 );
2494 dashPattern.push_back( 1.0 );
2495 dashPattern.push_back( 2.0 );
2498 case Qt::CustomDashLine:
2499 Q_ASSERT( customDashPattern );
2500 pattern = customDashPattern;
2504 context.
pushWarning( QObject::tr(
"Pen style '%1' is not supported for SLD" ).arg( penStyle ) );
2508 if ( color.isValid() )
2511 if ( color.alpha() < 255 )
2518 else if ( width == 0 )
2528 if ( !pattern->isEmpty() )
2538 QDomElement &element, Qt::PenStyle &penStyle, QColor &color,
double &width, Qt::PenJoinStyle *penJoinStyle, Qt::PenCapStyle *penCapStyle, QVector<qreal> *customDashPattern,
double *dashOffset
2543 penStyle = Qt::SolidLine;
2544 color = QColor( 0, 0, 0 );
2547 *penJoinStyle = Qt::BevelJoin;
2549 *penCapStyle = Qt::SquareCap;
2550 if ( customDashPattern )
2551 customDashPattern->clear();
2555 if ( element.isNull() )
2557 penStyle = Qt::NoPen;
2563 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2565 QgsDebugMsgLevel( u
"found SvgParameter %1: %2"_s.arg( it.key(), it.value() ), 2 );
2567 if ( it.key() ==
"stroke"_L1 )
2569 color = QColor( it.value() );
2571 else if ( it.key() ==
"stroke-opacity"_L1 )
2575 else if ( it.key() ==
"stroke-width"_L1 )
2578 const double w = it.value().toDouble( &ok );
2582 else if ( it.key() ==
"stroke-linejoin"_L1 && penJoinStyle )
2586 else if ( it.key() ==
"stroke-linecap"_L1 && penCapStyle )
2590 else if ( it.key() ==
"stroke-dasharray"_L1 )
2593 if ( !dashPattern.isEmpty() )
2597 bool dashPatternFound =
false;
2599 if ( dashPattern.count() == 2 )
2601 if ( dashPattern.at( 0 ) == 4.0 && dashPattern.at( 1 ) == 2.0 )
2603 penStyle = Qt::DashLine;
2604 dashPatternFound =
true;
2606 else if ( dashPattern.at( 0 ) == 1.0 && dashPattern.at( 1 ) == 2.0 )
2608 penStyle = Qt::DotLine;
2609 dashPatternFound =
true;
2612 else if ( dashPattern.count() == 4 )
2614 if ( dashPattern.at( 0 ) == 4.0 && dashPattern.at( 1 ) == 2.0 && dashPattern.at( 2 ) == 1.0 && dashPattern.at( 3 ) == 2.0 )
2616 penStyle = Qt::DashDotLine;
2617 dashPatternFound =
true;
2620 else if ( dashPattern.count() == 6 )
2622 if ( dashPattern.at( 0 ) == 4.0 && dashPattern.at( 1 ) == 2.0 && dashPattern.at( 2 ) == 1.0 && dashPattern.at( 3 ) == 2.0 && dashPattern.at( 4 ) == 1.0 && dashPattern.at( 5 ) == 2.0 )
2624 penStyle = Qt::DashDotDotLine;
2625 dashPatternFound =
true;
2630 if ( !dashPatternFound )
2632 if ( customDashPattern )
2634 penStyle = Qt::CustomDashLine;
2635 *customDashPattern = dashPattern;
2639 QgsDebugMsgLevel( u
"custom dash pattern required but not provided. Using default dash pattern."_s, 2 );
2640 penStyle = Qt::DashLine;
2645 else if ( it.key() ==
"stroke-dashoffset"_L1 && dashOffset )
2648 const double d = it.value().toDouble( &ok );
2659 QDomElement externalGraphicElem = doc.createElement( u
"se:ExternalGraphic"_s );
2660 element.appendChild( externalGraphicElem );
2669 QDomElement sizeElem = doc.createElement( u
"se:Size"_s );
2671 element.appendChild( sizeElem );
2678 parametricSvgToSld( doc, graphicElem, path, fillColor, size, strokeColor, strokeWidth, context );
2682 QDomDocument &doc, QDomElement &graphicElem,
const QString &path,
const QColor &fillColor,
double size,
const QColor &strokeColor,
double strokeWidth,
QgsSldExportContext &context
2690 graphicElem.appendChild( doc.createComment( u
"Parametric SVG"_s ) );
2691 const QString parametricPath =
getSvgParametricPath( path, fillColor, strokeColor, strokeWidth );
2694 graphicElem.appendChild( doc.createComment( u
"Plain SVG fallback, no parameters"_s ) );
2697 graphicElem.appendChild( doc.createComment( u
"Well known marker fallback"_s ) );
2703 QDomElement sizeElem = doc.createElement( u
"se:Size"_s );
2705 graphicElem.appendChild( sizeElem );
2712 if ( fillColor.isValid() )
2714 url.addQueryItem( u
"fill"_s, fillColor.name() );
2715 url.addQueryItem( u
"fill-opacity"_s,
encodeSldAlpha( fillColor.alpha() ) );
2719 url.addQueryItem( u
"fill"_s, u
"#000000"_s );
2720 url.addQueryItem( u
"fill-opacity"_s, u
"1"_s );
2722 if ( strokeColor.isValid() )
2724 url.addQueryItem( u
"outline"_s, strokeColor.name() );
2725 url.addQueryItem( u
"outline-opacity"_s,
encodeSldAlpha( strokeColor.alpha() ) );
2729 url.addQueryItem( u
"outline"_s, u
"#000000"_s );
2730 url.addQueryItem( u
"outline-opacity"_s, u
"1"_s );
2732 url.addQueryItem( u
"outline-width"_s, QString::number( strokeWidth ) );
2733 const QString params = url.toString( QUrl::FullyEncoded );
2734 if ( params.isEmpty() )
2740 return basePath +
"?" + params;
2749 QDomElement externalGraphicElem = element.firstChildElement( u
"ExternalGraphic"_s );
2750 if ( externalGraphicElem.isNull() )
2755 const QDomElement sizeElem = element.firstChildElement( u
"Size"_s );
2756 if ( !sizeElem.isNull() )
2759 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2774 QDomDocument &doc, QDomElement &element,
const QString &path,
const QString &format,
QgsSldExportContext &context,
int *markIndex,
const QColor &color,
double size
2777 QDomElement markElem = doc.createElement( u
"se:Mark"_s );
2778 element.appendChild( markElem );
2784 QDomElement markIndexElem = doc.createElement( u
"se:MarkIndex"_s );
2785 markIndexElem.appendChild( doc.createTextNode( QString::number( *markIndex ) ) );
2786 markElem.appendChild( markIndexElem );
2790 QDomElement fillElem = doc.createElement( u
"se:Fill"_s );
2791 fillToSld( doc, fillElem, context, Qt::SolidPattern, color );
2792 markElem.appendChild( fillElem );
2797 QDomElement sizeElem = doc.createElement( u
"se:Size"_s );
2799 element.appendChild( sizeElem );
2811 QDomElement markElem = element.firstChildElement( u
"Mark"_s );
2812 if ( markElem.isNull() )
2817 const QDomElement markIndexElem = markElem.firstChildElement( u
"MarkIndex"_s );
2818 if ( !markIndexElem.isNull() )
2821 const int i = markIndexElem.firstChild().nodeValue().toInt( &ok );
2827 QDomElement fillElem = markElem.firstChildElement( u
"Fill"_s );
2828 Qt::BrushStyle b = Qt::SolidPattern;
2833 const QDomElement sizeElem = element.firstChildElement( u
"Size"_s );
2834 if ( !sizeElem.isNull() )
2837 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2846 QDomDocument &doc, QDomElement &element,
const QString &name,
const QColor &color,
const QColor &strokeColor, Qt::PenStyle strokeStyle,
double strokeWidth,
double size
2850 wellKnownMarkerToSld( doc, element, name, color, strokeColor, strokeStyle, context, strokeWidth, size );
2854 QDomDocument &doc, QDomElement &element,
const QString &name,
const QColor &color,
const QColor &strokeColor, Qt::PenStyle strokeStyle,
QgsSldExportContext &context,
double strokeWidth,
double size
2857 QDomElement markElem = doc.createElement( u
"se:Mark"_s );
2858 element.appendChild( markElem );
2860 QDomElement wellKnownNameElem = doc.createElement( u
"se:WellKnownName"_s );
2861 wellKnownNameElem.appendChild( doc.createTextNode( name ) );
2862 markElem.appendChild( wellKnownNameElem );
2865 if ( color.isValid() )
2867 QDomElement fillElem = doc.createElement( u
"se:Fill"_s );
2868 fillToSld( doc, fillElem, context, Qt::SolidPattern, color );
2869 markElem.appendChild( fillElem );
2873 if ( strokeColor.isValid() )
2875 QDomElement strokeElem = doc.createElement( u
"se:Stroke"_s );
2876 lineToSld( doc, strokeElem, strokeStyle, strokeColor, context, strokeWidth );
2877 markElem.appendChild( strokeElem );
2883 QDomElement sizeElem = doc.createElement( u
"se:Size"_s );
2885 element.appendChild( sizeElem );
2895 strokeColor = QColor( 0, 0, 0 );
2899 const QDomElement markElem = element.firstChildElement( u
"Mark"_s );
2900 if ( markElem.isNull() )
2903 const QDomElement wellKnownNameElem = markElem.firstChildElement( u
"WellKnownName"_s );
2904 if ( !wellKnownNameElem.isNull() )
2906 name = wellKnownNameElem.firstChild().nodeValue();
2911 QDomElement fillElem = markElem.firstChildElement( u
"Fill"_s );
2912 Qt::BrushStyle b = Qt::SolidPattern;
2917 QDomElement strokeElem = markElem.firstChildElement( u
"Stroke"_s );
2918 lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth );
2922 const QDomElement sizeElem = element.firstChildElement( u
"Size"_s );
2923 if ( !sizeElem.isNull() )
2926 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2942 if ( !rotationFunc.isEmpty() )
2944 QDomElement rotationElem = doc.createElement( u
"se:Rotation"_s );
2946 element.appendChild( rotationElem );
2952 QDomElement rotationElem = element.firstChildElement( u
"Rotation"_s );
2953 if ( !rotationElem.isNull() )
2968 if ( !alphaFunc.isEmpty() )
2970 QDomElement opacityElem = doc.createElement( u
"se:Opacity"_s );
2972 element.appendChild( opacityElem );
2978 QDomElement opacityElem = element.firstChildElement( u
"Opacity"_s );
2979 if ( !opacityElem.isNull() )
2988 if ( offset.isNull() )
2991 QDomElement displacementElem = doc.createElement( u
"se:Displacement"_s );
2992 element.appendChild( displacementElem );
2994 QDomElement dispXElem = doc.createElement( u
"se:DisplacementX"_s );
2995 dispXElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.x(), 2 ) ) );
2997 QDomElement dispYElem = doc.createElement( u
"se:DisplacementY"_s );
2998 dispYElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.y(), 2 ) ) );
3000 displacementElem.appendChild( dispXElem );
3001 displacementElem.appendChild( dispYElem );
3008 QDomElement anchorElem = doc.createElement( u
"se:AnchorPoint"_s );
3009 element.appendChild( anchorElem );
3011 QDomElement anchorXElem = doc.createElement( u
"se:AnchorPointX"_s );
3012 anchorXElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.x() ) ) );
3014 QDomElement anchorYElem = doc.createElement( u
"se:AnchorPointY"_s );
3015 anchorYElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.y() ) ) );
3017 anchorElem.appendChild( anchorXElem );
3018 anchorElem.appendChild( anchorYElem );
3023 offset = QPointF( 0, 0 );
3025 const QDomElement displacementElem = element.firstChildElement( u
"Displacement"_s );
3026 if ( displacementElem.isNull() )
3029 const QDomElement dispXElem = displacementElem.firstChildElement( u
"DisplacementX"_s );
3030 if ( !dispXElem.isNull() )
3033 const double offsetX = dispXElem.firstChild().nodeValue().toDouble( &ok );
3035 offset.setX( offsetX );
3038 const QDomElement dispYElem = displacementElem.firstChildElement( u
"DisplacementY"_s );
3039 if ( !dispYElem.isNull() )
3042 const double offsetY = dispYElem.firstChild().nodeValue().toDouble( &ok );
3044 offset.setY( offsetY );
3053 labelTextToSld( doc, element, label, font, context, color, size );
3058 QDomElement labelElem = doc.createElement( u
"se:Label"_s );
3059 labelElem.appendChild( doc.createTextNode( label ) );
3060 element.appendChild( labelElem );
3062 QDomElement fontElem = doc.createElement( u
"se:Font"_s );
3063 element.appendChild( fontElem );
3067 fontElem.appendChild( createSldParameterElement( doc,
"font-style",
encodeSldFontStyle( font.style() ) ) );
3068 fontElem.appendChild( createSldParameterElement( doc,
"font-weight",
encodeSldFontWeight( font.weight() ) ) );
3073 if ( color.isValid() )
3075 QDomElement fillElem = doc.createElement( u
"Fill"_s );
3076 fillToSld( doc, fillElem, context, Qt::SolidPattern, color );
3077 element.appendChild( fillElem );
3082 double width,
double mmScaleFactor,
double mapUnitScaleFactor,
const QColor &
c, Qt::PenJoinStyle joinStyle, Qt::PenCapStyle capStyle,
double offset,
const QVector<qreal> *dashPattern
3086 penStyle.append(
"PEN(" );
3087 penStyle.append(
"c:" );
3088 penStyle.append(
c.name() );
3089 penStyle.append(
",w:" );
3091 penStyle.append( QString::number( width * mmScaleFactor ) );
3092 penStyle.append(
"mm" );
3095 if ( dashPattern && !dashPattern->isEmpty() )
3097 penStyle.append(
",p:\"" );
3098 QVector<qreal>::const_iterator pIt = dashPattern->constBegin();
3099 for ( ; pIt != dashPattern->constEnd(); ++pIt )
3101 if ( pIt != dashPattern->constBegin() )
3103 penStyle.append(
' ' );
3105 penStyle.append( QString::number( *pIt * mapUnitScaleFactor ) );
3106 penStyle.append(
'g' );
3108 penStyle.append(
'\"' );
3112 penStyle.append(
",cap:" );
3116 penStyle.append(
'p' );
3119 penStyle.append(
'r' );
3123 penStyle.append(
'b' );
3127 penStyle.append(
",j:" );
3128 switch ( joinStyle )
3131 penStyle.append(
'b' );
3134 penStyle.append(
'r' );
3138 penStyle.append(
'm' );
3144 penStyle.append(
",dp:" );
3145 penStyle.append( QString::number( offset * mapUnitScaleFactor ) );
3146 penStyle.append(
'g' );
3149 penStyle.append(
')' );
3156 brushStyle.append(
"BRUSH(" );
3157 brushStyle.append(
"fc:" );
3158 brushStyle.append( fillColor.name() );
3159 brushStyle.append(
')' );
3171 if ( geomFunc.isEmpty() )
3174 QDomElement geometryElem = doc.createElement( u
"Geometry"_s );
3175 element.appendChild( geometryElem );
3205 QDomElement geometryElem = element.firstChildElement( u
"Geometry"_s );
3206 if ( geometryElem.isNull() )
3224 context.
pushError( QObject::tr(
"Parser error encountered when converting expression to SLD: %1 - Expression was: %2" ).arg( expr.
parserErrorString(), function ) );
3228 if ( !filterElem.isNull() )
3229 element.appendChild( filterElem );
3242 if ( function ==
"ELSE"_L1 )
3245 element.appendChild( filterElem );
3254 context.
pushError( QObject::tr(
"Parser error encountered when converting expression to SLD: %1 - Expression was: %2" ).arg( expr.
parserErrorString(), function ) );
3258 if ( !filterElem.isNull() )
3259 element.appendChild( filterElem );
3267 QDomElement elem = element;
3268 if ( element.tagName() !=
"Filter"_L1 )
3270 const QDomNodeList filterNodes = element.elementsByTagName( u
"Filter"_s );
3271 if ( !filterNodes.isEmpty() )
3273 elem = filterNodes.at( 0 ).toElement();
3277 if ( elem.isNull() )
3305 QDomElement onlineResourceElem = doc.createElement( u
"se:OnlineResource"_s );
3306 onlineResourceElem.setAttribute( u
"xlink:type"_s, u
"simple"_s );
3307 onlineResourceElem.setAttribute( u
"xlink:href"_s, url );
3308 element.appendChild( onlineResourceElem );
3310 QDomElement formatElem = doc.createElement( u
"se:Format"_s );
3311 formatElem.appendChild( doc.createTextNode( format ) );
3312 element.appendChild( formatElem );
3319 const QDomElement onlineResourceElem = element.firstChildElement( u
"OnlineResource"_s );
3320 if ( onlineResourceElem.isNull() )
3323 path = QUrl::fromPercentEncoding( onlineResourceElem.attributeNS( u
"http://www.w3.org/1999/xlink"_s, u
"href"_s ).toUtf8() );
3325 const QDomElement formatElem = element.firstChildElement( u
"Format"_s );
3326 if ( formatElem.isNull() )
3329 format = formatElem.firstChild().nodeValue();
3336 QDomElement nodeElem = doc.createElement( u
"se:SvgParameter"_s );
3337 nodeElem.setAttribute( u
"name"_s, name );
3338 nodeElem.appendChild( doc.createTextNode( value ) );
3347 QDomElement paramElem = element.firstChildElement();
3348 while ( !paramElem.isNull() )
3350 if ( paramElem.localName() ==
"SvgParameter"_L1 || paramElem.localName() ==
"CssParameter"_L1 )
3352 const QString name = paramElem.attribute( u
"name"_s );
3353 if ( paramElem.firstChild().nodeType() == QDomNode::TextNode )
3355 value = paramElem.firstChild().nodeValue();
3359 if ( paramElem.firstChild().nodeType() == QDomNode::ElementNode && paramElem.firstChild().localName() ==
"Literal"_L1 )
3362 value = paramElem.firstChild().firstChild().nodeValue();
3366 QgsDebugError( u
"unexpected child of %1"_s.arg( paramElem.localName() ) );
3370 if ( !name.isEmpty() && !value.isEmpty() )
3371 params[name] = value;
3374 paramElem = paramElem.nextSiblingElement();
3382 QDomElement nodeElem = doc.createElement( u
"se:VendorOption"_s );
3383 nodeElem.setAttribute( u
"name"_s, name );
3384 nodeElem.appendChild( doc.createTextNode( value ) );
3392 QDomElement paramElem = element.firstChildElement( u
"VendorOption"_s );
3393 while ( !paramElem.isNull() )
3395 const QString name = paramElem.attribute( u
"name"_s );
3396 const QString value = paramElem.firstChild().nodeValue();
3398 if ( !name.isEmpty() && !value.isEmpty() )
3399 params[name] = value;
3401 paramElem = paramElem.nextSiblingElement( u
"VendorOption"_s );
3411 if ( newSymbols.userType() == QMetaType::Type::QVariantMap )
3413 return newSymbols.toMap();
3420 QDomElement e = element.firstChildElement();
3421 while ( !e.isNull() )
3423 if ( e.tagName() ==
"prop"_L1 )
3425 const QString propKey = e.attribute( u
"k"_s );
3426 const QString propValue = e.attribute( u
"v"_s );
3427 props[propKey] = propValue;
3429 e = e.nextSiblingElement();
3446 QDomElement e = element.firstChildElement();
3448 while ( !e.isNull() )
3450 if ( e.tagName() ==
"symbol"_L1 )
3454 symbols.insert( e.attribute( u
"name"_s ), symbol.release() );
3460 e = e.nextSiblingElement();
3467 QStringList subsymbols;
3469 for ( QMap<QString, QgsSymbol *>::iterator it = symbols.begin(); it != symbols.end(); ++it )
3471 if ( it.key()[0] !=
'@' )
3475 subsymbols.append( it.key() );
3477 QStringList parts = it.key().split(
'@' );
3478 if ( parts.count() < 3 )
3480 QgsDebugError(
"found subsymbol with invalid name: " + it.key() );
3484 const QString symname = parts[1];
3485 const int symlayer = parts[2].toInt();
3487 if ( !symbols.contains( symname ) )
3489 QgsDebugError(
"subsymbol references invalid symbol: " + symname );
3497 QgsDebugError(
"subsymbol references invalid symbol layer: " + QString::number( symlayer ) );
3506 QgsDebugError(
"symbol layer refused subsymbol: " + it.key() );
3511 for (
int i = 0; i < subsymbols.count(); i++ )
3512 symbols.take( subsymbols[i] );
3519 QDomElement symbolsElem = doc.createElement( tagName );
3522 for ( QMap<QString, QgsSymbol *>::iterator its = symbols.begin(); its != symbols.end(); ++its )
3524 const QDomElement symEl =
saveSymbol( its.key(), its.value(), doc, context );
3525 symbolsElem.appendChild( symEl );
3533 qDeleteAll( symbols );
3542 std::unique_ptr< QMimeData > mimeData(
new QMimeData );
3544 QDomDocument symbolDoc;
3546 symbolDoc.appendChild( symbolElem );
3547 mimeData->setText( symbolDoc.toString() );
3550 mimeData->setColorData( symbol->
color() );
3552 return mimeData.release();
3560 const QString text = data->text();
3561 if ( !text.isEmpty() )
3566 if ( doc.setContent( text ) )
3568 elem = doc.documentElement();
3570 if ( elem.nodeName() !=
"symbol"_L1 )
3571 elem = elem.firstChildElement( u
"symbol"_s );
3582 const QString rampType = element.attribute( u
"type"_s );
3607 QDomElement rampEl = doc.createElement( u
"colorramp"_s );
3608 rampEl.setAttribute( u
"type"_s, ramp->
type() );
3609 rampEl.setAttribute( u
"name"_s, name );
3617 QVariantMap rampMap;
3619 rampMap.insert( u
"type"_s, ramp->
type() );
3620 rampMap.insert( u
"name"_s, name );
3622 const QVariantMap properties = ramp->
properties();
3624 QVariantMap propertyMap;
3625 for (
auto property = properties.constBegin(); property != properties.constEnd(); ++property )
3627 propertyMap.insert( property.key(), property.value() );
3630 rampMap.insert( u
"properties"_s, propertyMap );
3636 const QVariantMap rampMap = value.toMap();
3638 const QString rampType = rampMap.value( u
"type"_s ).toString();
3641 const QVariantMap propertyMap = rampMap.value( u
"properties"_s ).toMap();
3644 for (
auto property = propertyMap.constBegin(); property != propertyMap.constEnd(); ++property )
3646 props.insert( property.key(), property.value().toString() );
3668 if ( !color.isValid() )
3675 return color.name();
3680 QList<QColor> colors;
3683 const thread_local QRegularExpression sepCommaSpaceRegExp(
"(,|\\s)" );
3684 QStringList components = colorStr.simplified().split( sepCommaSpaceRegExp );
3685 QStringList::iterator it = components.begin();
3686 for ( ; it != components.end(); ++it )
3688 const QColor result =
parseColor( *it,
true );
3689 if ( result.isValid() )
3694 if ( colors.length() > 0 )
3700 const thread_local QRegularExpression sepCommaRegExp(
"(,|\n)" );
3701 components = colorStr.split( sepCommaRegExp );
3702 it = components.begin();
3703 for ( ; it != components.end(); ++it )
3705 const QColor result =
parseColor( *it,
true );
3706 if ( result.isValid() )
3711 if ( colors.length() > 0 )
3717 components = colorStr.simplified().split( QString(
' ' ) );
3718 it = components.begin();
3719 for ( ; it != components.end(); ++it )
3721 const QColor result =
parseColor( *it,
true );
3722 if ( result.isValid() )
3727 if ( colors.length() > 0 )
3733 components = colorStr.split(
'\n' );
3734 it = components.begin();
3735 for ( ; it != components.end(); ++it )
3737 const QColor result =
parseColor( *it,
true );
3738 if ( result.isValid() )
3751 QMimeData *mimeData =
new QMimeData;
3752 mimeData->setColorData( QVariant( color ) );
3753 mimeData->setText( color.name() );
3763 if ( mimeData->hasColor() )
3765 QColor mimeColor = mimeData->colorData().value<QColor>();
3766 if ( mimeColor.isValid() )
3774 if ( mimeData->hasText() )
3778 if ( textColor.isValid() )
3796 if ( data->hasFormat( u
"text/xml"_s ) )
3799 const QByteArray encodedData = data->data( u
"text/xml"_s );
3800 QDomDocument xmlDoc;
3801 xmlDoc.setContent( encodedData );
3803 const QDomElement dragDataElem = xmlDoc.documentElement();
3804 if ( dragDataElem.tagName() ==
"ColorSchemeModelDragData"_L1 )
3806 const QDomNodeList nodeList = dragDataElem.childNodes();
3807 const int nChildNodes = nodeList.size();
3808 QDomElement currentElem;
3810 for (
int i = 0; i < nChildNodes; ++i )
3812 currentElem = nodeList.at( i ).toElement();
3813 if ( currentElem.isNull() )
3818 QPair< QColor, QString> namedColor;
3820 namedColor.second = currentElem.attribute( u
"label"_s, QString() );
3822 mimeColors << namedColor;
3827 if ( mimeColors.length() == 0 && data->hasFormat( u
"application/x-colorobject-list"_s ) )
3830 const QByteArray encodedData = data->data( u
"application/x-colorobject-list"_s );
3831 QDomDocument xmlDoc;
3832 xmlDoc.setContent( encodedData );
3834 const QDomNodeList colorsNodes = xmlDoc.elementsByTagName( u
"colors"_s );
3835 if ( colorsNodes.length() > 0 )
3837 const QDomElement colorsElem = colorsNodes.at( 0 ).toElement();
3838 const QDomNodeList colorNodeList = colorsElem.childNodes();
3839 const int nChildNodes = colorNodeList.size();
3840 QDomElement currentElem;
3842 for (
int i = 0; i < nChildNodes; ++i )
3845 currentElem = colorNodeList.at( i ).toElement();
3846 if ( currentElem.isNull() )
3851 const QDomNodeList colorNodes = currentElem.elementsByTagName( u
"color"_s );
3852 const QDomNodeList nameNodes = currentElem.elementsByTagName( u
"name"_s );
3854 if ( colorNodes.length() > 0 )
3856 const QDomElement colorElem = colorNodes.at( 0 ).toElement();
3858 const QStringList colorParts = colorElem.text().simplified().split(
' ' );
3859 if ( colorParts.length() < 3 )
3864 const int red = colorParts.at( 0 ).toDouble() * 255;
3865 const int green = colorParts.at( 1 ).toDouble() * 255;
3866 const int blue = colorParts.at( 2 ).toDouble() * 255;
3867 QPair< QColor, QString> namedColor;
3868 namedColor.first = QColor( red, green, blue );
3869 if ( nameNodes.length() > 0 )
3871 const QDomElement nameElem = nameNodes.at( 0 ).toElement();
3872 namedColor.second = nameElem.text();
3874 mimeColors << namedColor;
3880 if ( mimeColors.length() == 0 && data->hasText() )
3884 QList< QColor >::iterator it = parsedColors.begin();
3885 for ( ; it != parsedColors.end(); ++it )
3887 mimeColors << qMakePair( *it, QString() );
3891 if ( mimeColors.length() == 0 && data->hasColor() )
3894 const QColor mimeColor = data->colorData().value<QColor>();
3895 if ( mimeColor.isValid() )
3897 mimeColors << qMakePair( mimeColor, QString() );
3907 QMimeData *mimeData =
new QMimeData();
3908 QDomDocument xmlDoc;
3909 QDomElement xmlRootElement = xmlDoc.createElement( u
"ColorSchemeModelDragData"_s );
3910 xmlDoc.appendChild( xmlRootElement );
3912 QgsNamedColorList::const_iterator colorIt = colorList.constBegin();
3913 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3915 QDomElement namedColor = xmlDoc.createElement( u
"NamedColor"_s );
3917 namedColor.setAttribute( u
"label"_s, ( *colorIt ).second );
3918 xmlRootElement.appendChild( namedColor );
3920 mimeData->setData( u
"text/xml"_s, xmlDoc.toByteArray() );
3928 colorIt = colorList.constBegin();
3929 QStringList colorListString;
3930 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3932 colorListString << ( *colorIt ).first.name();
3934 mimeData->setText( colorListString.join( QLatin1Char(
'\n' ) ) );
3937 if ( colorList.length() > 0 )
3939 mimeData->setColorData( QVariant( colorList.at( 0 ).first ) );
3947 if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3952 QTextStream stream( &file );
3954 stream <<
"GIMP Palette" << Qt::endl;
3955 if ( paletteName.isEmpty() )
3957 stream <<
"Name: QGIS Palette" << Qt::endl;
3961 stream <<
"Name: " << paletteName << Qt::endl;
3963 stream <<
"Columns: 4" << Qt::endl;
3964 stream <<
'#' << Qt::endl;
3966 for ( QgsNamedColorList::ConstIterator colorIt = colors.constBegin(); colorIt != colors.constEnd(); ++colorIt )
3968 const QColor color = ( *colorIt ).first;
3969 if ( !color.isValid() )
3973 stream << u
"%1 %2 %3"_s.arg( color.red(), 3 ).arg( color.green(), 3 ).arg( color.blue(), 3 );
3974 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << Qt::endl;
3985 if ( !file.open( QIODevice::ReadOnly ) )
3988 return importedColors;
3991 QTextStream in( &file );
3993 QString line = in.readLine();
3994 if ( !line.startsWith(
"GIMP Palette"_L1 ) )
3997 return importedColors;
4001 while ( !in.atEnd() && !line.startsWith(
"Name:"_L1 ) && !line.startsWith(
'#' ) )
4003 line = in.readLine();
4005 if ( line.startsWith(
"Name:"_L1 ) )
4007 const thread_local QRegularExpression nameRx(
"Name:\\s*(\\S.*)$" );
4008 const QRegularExpressionMatch match = nameRx.match( line );
4009 if ( match.hasMatch() )
4011 name = match.captured( 1 );
4016 while ( !in.atEnd() && !line.startsWith(
'#' ) )
4018 line = in.readLine();
4023 return importedColors;
4027 const thread_local QRegularExpression rx(
"^\\s*(\\d+)\\s+(\\d+)\\s+(\\d+)(\\s.*)?$" );
4028 while ( !in.atEnd() )
4030 line = in.readLine();
4031 const QRegularExpressionMatch match = rx.match( line );
4032 if ( !match.hasMatch() )
4036 const int red = match.captured( 1 ).toInt();
4037 const int green = match.captured( 2 ).toInt();
4038 const int blue = match.captured( 3 ).toInt();
4039 const QColor color = QColor( red, green, blue );
4040 if ( !color.isValid() )
4047 if ( rx.captureCount() > 3 )
4049 label = match.captured( 4 ).simplified();
4056 importedColors << qMakePair( color, label );
4061 return importedColors;
4074 const thread_local QRegularExpression hexColorAlphaRx(
"^\\s*#?([0-9a-fA-F]{6})([0-9a-fA-F]{2})\\s*$" );
4075 QRegularExpressionMatch match = hexColorAlphaRx.match( colorStr );
4078 if ( !match.hasMatch() && QColor::isValidColor( colorStr ) )
4081 parsedColor.setNamedColor( colorStr );
4082 if ( parsedColor.isValid() )
4084 containsAlpha =
false;
4090 if ( match.hasMatch() )
4092 const QString hexColor = match.captured( 1 );
4093 parsedColor.setNamedColor( u
"#"_s + hexColor );
4095 const int alphaHex = match.captured( 2 ).toInt( &alphaOk, 16 );
4097 if ( parsedColor.isValid() && alphaOk )
4099 parsedColor.setAlpha( alphaHex );
4100 containsAlpha =
true;
4108 const thread_local QRegularExpression hexColorRx2(
"^\\s*(?:[0-9a-fA-F]{3}){1,2}\\s*$" );
4109 if ( colorStr.indexOf( hexColorRx2 ) != -1 )
4112 parsedColor.setNamedColor( u
"#"_s + colorStr );
4113 if ( parsedColor.isValid() )
4115 containsAlpha =
false;
4122 const thread_local QRegularExpression rgbFormatRx(
4123 "^\\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])(?:\\."
4124 "\\d*)?)\\s*\\)?\\s*;?\\s*$"
4126 match = rgbFormatRx.match( colorStr );
4127 if ( match.hasMatch() )
4132 const int r = match.captured( 1 ).toInt( &rOk );
4133 const int g = match.captured( 2 ).toInt( &gOk );
4134 const int b = match.captured( 3 ).toInt( &bOk );
4136 if ( !rOk || !gOk || !bOk )
4138 const float rFloat = match.captured( 1 ).toFloat();
4139 const float gFloat = match.captured( 2 ).toFloat();
4140 const float bFloat = match.captured( 3 ).toFloat();
4141 parsedColor.setRgbF( rFloat / 255.0, gFloat / 255.0, bFloat / 255.0 );
4145 parsedColor.setRgb( r, g, b );
4148 if ( parsedColor.isValid() )
4150 containsAlpha =
false;
4156 const thread_local QRegularExpression hslFormatRx(
"^\\s*hsl\\(?\\s*(\\d+(?:\\.\\d*)?)\\s*,\\s*(\\d+(?:\\.\\d*)?)\\s*%\\s*,\\s*(\\d+(?:\\.\\d*)?)\\s*%\\s*\\)?\\s*;?\\s*$" );
4157 match = hslFormatRx.match( colorStr );
4158 if ( match.hasMatch() )
4163 const int h = match.captured( 1 ).toInt( &hOk );
4164 const int s = match.captured( 2 ).toInt( &sOk );
4165 const int l = match.captured( 3 ).toInt( &lOk );
4167 if ( !hOk || !sOk || !lOk )
4169 const float hFloat = match.captured( 1 ).toFloat();
4170 const float sFloat = match.captured( 2 ).toFloat();
4171 const float lFloat = match.captured( 3 ).toFloat();
4172 parsedColor.setHslF( hFloat / 360.0, sFloat / 100.0, lFloat / 100.0 );
4176 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0 );
4178 if ( parsedColor.isValid() )
4180 containsAlpha =
false;
4186 const thread_local QRegularExpression rgbPercentFormatRx(
4187 "^\\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*$"
4189 match = rgbPercentFormatRx.match( colorStr );
4190 if ( match.hasMatch() )
4192 const double r = match.captured( 1 ).toDouble() / 100;
4193 const double g = match.captured( 2 ).toDouble() / 100;
4194 const double b = match.captured( 3 ).toDouble() / 100;
4195 parsedColor.setRgbF( r, g, b );
4196 if ( parsedColor.isValid() )
4198 containsAlpha =
false;
4204 const thread_local QRegularExpression rgbaFormatRx(
4205 "^\\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])(?:"
4206 "\\.\\d*)?)\\s*,\\s*(0|0?\\.\\d*|1(?:\\.0*)?)\\s*\\)?\\s*;?\\s*$"
4208 match = rgbaFormatRx.match( colorStr );
4209 if ( match.hasMatch() )
4214 const int r = match.captured( 1 ).toInt( &rOk );
4215 const int g = match.captured( 2 ).toInt( &gOk );
4216 const int b = match.captured( 3 ).toInt( &bOk );
4217 const double aDouble = match.captured( 4 ).toDouble();
4219 if ( !rOk || !gOk || !bOk )
4221 const float rFloat = match.captured( 1 ).toFloat();
4222 const float gFloat = match.captured( 2 ).toFloat();
4223 const float bFloat = match.captured( 3 ).toFloat();
4224 parsedColor.setRgbF( rFloat / 255.0, gFloat / 255.0, bFloat / 255.0, aDouble );
4228 const int a =
static_cast< int >( std::round( match.captured( 4 ).toDouble() * 255.0 ) );
4229 parsedColor.setRgb( r, g, b, a );
4231 if ( parsedColor.isValid() )
4233 containsAlpha =
true;
4239 const thread_local QRegularExpression rgbaPercentFormatRx(
4240 "^\\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*$"
4242 match = rgbaPercentFormatRx.match( colorStr );
4243 if ( match.hasMatch() )
4245 const double r = match.captured( 1 ).toDouble() / 100;
4246 const double g = match.captured( 2 ).toDouble() / 100;
4247 const double b = match.captured( 3 ).toDouble() / 100;
4248 const double a = match.captured( 4 ).toDouble();
4249 parsedColor.setRgbF( r, g, b, a );
4250 if ( parsedColor.isValid() )
4252 containsAlpha =
true;
4258 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*$" );
4259 match = hslaPercentFormatRx.match( colorStr );
4260 if ( match.hasMatch() )
4265 const int h = match.captured( 1 ).toInt( &hOk );
4266 const int s = match.captured( 2 ).toInt( &sOk );
4267 const int l = match.captured( 3 ).toInt( &lOk );
4268 const double aDouble = match.captured( 4 ).toDouble();
4270 if ( !hOk || !sOk || !lOk )
4272 const float hFloat = match.captured( 1 ).toFloat();
4273 const float sFloat = match.captured( 2 ).toFloat();
4274 const float lFloat = match.captured( 3 ).toFloat();
4275 parsedColor.setHslF( hFloat / 360.0, sFloat / 100.0, lFloat / 100.0, aDouble );
4279 const int a = std::round( aDouble * 255.0 );
4280 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0, a );
4283 if ( parsedColor.isValid() )
4285 containsAlpha =
true;
4302 const QImage::Format format = image->format();
4303 if ( format != QImage::Format_ARGB32_Premultiplied && format != QImage::Format_ARGB32 )
4310 for (
int heightIndex = 0; heightIndex < image->height(); ++heightIndex )
4312 QRgb *scanLine =
reinterpret_cast< QRgb *
>( image->scanLine( heightIndex ) );
4313 for (
int widthIndex = 0; widthIndex < image->width(); ++widthIndex )
4315 myRgb = scanLine[widthIndex];
4316 if ( format == QImage::Format_ARGB32_Premultiplied )
4317 scanLine[widthIndex] = qRgba( opacity * qRed( myRgb ), opacity * qGreen( myRgb ), opacity * qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4319 scanLine[widthIndex] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4327 const int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
4328 const int alpha = ( radius < 1 ) ? 16 : ( radius > 17 ) ? 1 : tab[radius - 1];
4330 if ( image.format() != QImage::Format_ARGB32_Premultiplied && image.format() != QImage::Format_RGB32 )
4332 image = image.convertToFormat( QImage::Format_ARGB32_Premultiplied );
4335 const int r1 = rect.top();
4336 const int r2 = rect.bottom();
4337 const int c1 = rect.left();
4338 const int c2 = rect.right();
4340 const int bpl = image.bytesPerLine();
4348 i1 = i2 = ( QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3 );
4350 for (
int col = c1; col <= c2; col++ )
4352 p = image.scanLine( r1 ) + col * 4;
4353 for (
int i = i1; i <= i2; i++ )
4354 rgba[i] = p[i] << 4;
4357 for (
int j = r1; j < r2; j++, p += bpl )
4358 for (
int i = i1; i <= i2; i++ )
4359 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4362 for (
int row = r1; row <= r2; row++ )
4364 p = image.scanLine( row ) + c1 * 4;
4365 for (
int i = i1; i <= i2; i++ )
4366 rgba[i] = p[i] << 4;
4369 for (
int j = c1; j < c2; j++, p += 4 )
4370 for (
int i = i1; i <= i2; i++ )
4371 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4374 for (
int col = c1; col <= c2; col++ )
4376 p = image.scanLine( r2 ) + col * 4;
4377 for (
int i = i1; i <= i2; i++ )
4378 rgba[i] = p[i] << 4;
4381 for (
int j = r1; j < r2; j++, p -= bpl )
4382 for (
int i = i1; i <= i2; i++ )
4383 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4386 for (
int row = r1; row <= r2; row++ )
4388 p = image.scanLine( row ) + c2 * 4;
4389 for (
int i = i1; i <= i2; i++ )
4390 rgba[i] = p[i] << 4;
4393 for (
int j = c1; j < c2; j++, p -= 4 )
4394 for (
int i = i1; i <= i2; i++ )
4395 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4401 if ( alpha != 255 && alpha > 0 )
4405 const double alphaFactor = alpha / 255.;
4406 int r = 0, g = 0, b = 0;
4407 rgb.getRgb( &r, &g, &b );
4412 rgb.setRgb( r, g, b, alpha );
4414 else if ( alpha == 0 )
4416 rgb.setRgb( 0, 0, 0, 0 );
4425 if ( !simpleFill || !simpleLine )
4449 if ( simpleLine->
offset() )
4467 if ( order == Qt::AscendingOrder )
4481 const double dx = directionPoint.x() - startPoint.x();
4482 const double dy = directionPoint.y() - startPoint.y();
4483 const double length = std::sqrt( dx * dx + dy * dy );
4484 const double scaleFactor = distance / length;
4485 return QPointF( startPoint.x() + dx * scaleFactor, startPoint.y() + dy * scaleFactor );
4495 for (
int i = 0; i < svgPaths.size(); i++ )
4497 const QDir dir( svgPaths[i] );
4498 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4499 for (
const QString &item : svgSubPaths )
4501 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4504 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4505 for (
const QString &item : svgFiles )
4508 list.append( dir.path() +
'/' + item );
4520 QStringList svgPaths;
4521 svgPaths.append( directory );
4523 for (
int i = 0; i < svgPaths.size(); i++ )
4525 const QDir dir( svgPaths[i] );
4526 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4527 for (
const QString &item : svgSubPaths )
4529 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4532 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4533 for (
const QString &item : svgFiles )
4535 list.append( dir.path() +
'/' + item );
4546 if ( n.startsWith(
"base64:"_L1 ) )
4550 if ( QFileInfo::exists( n ) )
4551 return QFileInfo( n ).canonicalFilePath();
4555 if ( name.contains(
"://"_L1 ) )
4557 const QUrl url( name );
4558 if ( url.isValid() && !url.scheme().isEmpty() )
4560 if ( url.scheme().compare(
"file"_L1, Qt::CaseInsensitive ) == 0 )
4563 name = url.toLocalFile();
4564 if ( QFile( name ).exists() )
4566 return QFileInfo( name ).canonicalFilePath();
4580 for (
int i = 0; i < svgPaths.size(); i++ )
4582 QString svgPath = svgPaths[i];
4583 if ( svgPath.endsWith( QChar(
'/' ) ) )
4594 const QString myLocalPath = svgPath + QDir::separator() + name;
4597 if ( QFile( myLocalPath ).exists() )
4600 return QFileInfo( myLocalPath ).canonicalFilePath();
4604 return pathResolver.
readPath( name );
4612 if ( p.startsWith(
"base64:"_L1 ) )
4615 if ( !QFileInfo::exists( p ) )
4618 QString path = QFileInfo( p ).canonicalFilePath();
4622 bool isInSvgPaths =
false;
4623 for (
int i = 0; i < svgPaths.size(); i++ )
4625 const QString dir = QFileInfo( svgPaths[i] ).canonicalFilePath();
4627 if ( !dir.isEmpty() && path.startsWith( dir ) )
4629 path = path.mid( dir.size() + 1 );
4630 isInSvgPaths =
true;
4643 const double *srcX = line->
xData();
4644 const double *srcY = line->
yData();
4646 QPolygonF thisRes( count );
4647 QPointF *dest = thisRes.data();
4648 for (
int i = 0; i < count; ++i )
4650 *dest++ = QPointF( *srcX++, *srcY++ );
4663 const std::unique_ptr< QgsLineString > straightened( curve->
curveToLine() );
4687 points << QPointF( ( *it ).x(), ( *it ).y() );
4691 points << QPointF( 0, 0 );
4693 return QList< QList<QPolygonF> >() << ( QList< QPolygonF >() << points );
4698 QList< QList<QPolygonF> > res;
4711 QList< QList<QPolygonF> > res;
4715 QList<QPolygonF> thisPart;
4734 return QList< QList<QPolygonF> >();
4737 return QList< QList<QPolygonF> >();
4744 double cx = 0, cy = 0;
4745 double area, sum = 0;
4746 for (
int i = points.count() - 1, j = 0; j < points.count(); i = j++ )
4748 const QPointF &p1 = points[i];
4749 const QPointF &p2 = points[j];
4750 area = p1.x() * p2.y() - p1.y() * p2.x();
4752 cx += ( p1.x() + p2.x() ) * area;
4753 cy += ( p1.y() + p2.y() ) * area;
4760 if ( points.count() >= 2 )
4761 return QPointF( ( points[0].x() + points[1].x() ) / 2, ( points[0].y() + points[1].y() ) / 2 );
4762 else if ( points.count() == 1 )
4770 return QPointF( cx, cy );
4777 if ( ( rings && rings->count() > 0 ) || !
pointInPolygon( points, centroid ) )
4779 unsigned int i, pointCount = points.count();
4781 for ( i = 0; i < pointCount; ++i )
4782 polyline[i] =
QgsPointXY( points[i].x(), points[i].y() );
4788 for (
auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
4790 pointCount = ( *ringIt ).count();
4792 for ( i = 0; i < pointCount; ++i )
4793 polyline[i] =
QgsPointXY( ( *ringIt )[i].x(), ( *ringIt )[i].y() );
4799 if ( !pointOnSurfaceGeom.
isNull() )
4802 centroid.
setX( point.
x() );
4803 centroid.setY( point.
y() );
4808 return QPointF( centroid.x(), centroid.y() );
4813 bool inside =
false;
4815 const double x = point.x();
4816 const double y = point.y();
4818 for (
int i = 0, j = points.count() - 1; i < points.count(); i++ )
4820 const QPointF &p1 = points[i];
4821 const QPointF &p2 = points[j];
4826 if ( ( p1.y() < y && p2.y() >= y ) || ( p2.y() < y && p1.y() >= y ) )
4828 if ( p1.x() + ( y - p1.y() ) / ( p2.y() - p1.y() ) * ( p2.x() - p1.x() ) <= x )
4839 if ( polyline.size() < 2 )
4842 double totalLength = 0;
4843 auto it = polyline.begin();
4845 for ( ; it != polyline.end(); ++it )
4847 const QPointF p2 = *it;
4848 const double segmentLength = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4849 totalLength += segmentLength;
4857 if ( polyline.size() < 2 )
4860 double totalLength = 0;
4861 auto it = polyline.begin();
4863 std::vector< double > segmentLengths( polyline.size() - 1 );
4864 auto segmentLengthIt = segmentLengths.begin();
4865 for ( ; it != polyline.end(); ++it )
4867 const QPointF p2 = *it;
4868 *segmentLengthIt = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4869 totalLength += *segmentLengthIt;
4875 if ( startOffset >= 0 && totalLength <= startOffset )
4877 if ( endOffset < 0 && totalLength <= -endOffset )
4880 const double startDistance = startOffset < 0 ? totalLength + startOffset : startOffset;
4881 const double endDistance = endOffset <= 0 ? totalLength + endOffset : endOffset;
4882 QPolygonF substringPoints;
4883 substringPoints.reserve( polyline.size() );
4885 it = polyline.begin();
4886 segmentLengthIt = segmentLengths.begin();
4889 bool foundStart =
false;
4890 if (
qgsDoubleNear( startDistance, 0.0 ) || startDistance < 0 )
4892 substringPoints << p1;
4896 double distanceTraversed = 0;
4897 for ( ; it != polyline.end(); ++it )
4899 const QPointF p2 = *it;
4900 if ( distanceTraversed < startDistance && distanceTraversed + *segmentLengthIt > startDistance )
4903 const double distanceToStart = startDistance - distanceTraversed;
4904 double startX, startY;
4906 substringPoints << QPointF( startX, startY );
4909 if ( foundStart && ( distanceTraversed + *segmentLengthIt > endDistance ) )
4912 const double distanceToEnd = endDistance - distanceTraversed;
4915 if ( substringPoints.last() != QPointF( endX, endY ) )
4916 substringPoints << QPointF( endX, endY );
4918 else if ( foundStart )
4920 if ( substringPoints.last() != QPointF( p2.x(), p2.y() ) )
4921 substringPoints << QPointF( p2.x(), p2.y() );
4924 distanceTraversed += *segmentLengthIt;
4925 if ( distanceTraversed > endDistance )
4932 if ( ( substringPoints.size() < 2 ) || ( substringPoints.size() == 2 && substringPoints.at( 0 ) == substringPoints.at( 1 ) ) )
4935 return substringPoints;
4940 double vertexAngle = M_PI - ( std::atan2( p3.y() - p2.y(), p3.x() - p2.x() ) - std::atan2( p2.y() - p1.y(), p2.x() - p1.x() ) );
4944 return vertexAngle < M_PI * 135.0 / 180.0 || vertexAngle > M_PI * 225.0 / 180.0;
4949 target.reserve( target.size() + line.size() );
4950 for (
const QPointF &pt : line )
4952 if ( !target.empty() && target.last() == pt )
4961 if ( fieldOrExpression.isEmpty() )
4964 auto expr = std::make_unique< QgsExpression >( fieldOrExpression );
4965 if ( !expr->hasParserError() )
4970 Q_ASSERT( !expr->hasParserError() );
4995 QList<double> breaks;
4998 breaks.append( maximum );
5002 const int minimumCount =
static_cast< int >( classes ) / 3;
5003 const double shrink = 0.75;
5004 const double highBias = 1.5;
5005 const double adjustBias = 0.5 + 1.5 * highBias;
5006 const int divisions = classes;
5007 const double h = highBias;
5010 const double dx = maximum - minimum;
5020 cell = std::max( std::fabs( minimum ), std::fabs( maximum ) );
5021 if ( adjustBias >= 1.5 * h + 0.5 )
5023 U = 1 + ( 1.0 / ( 1 + h ) );
5027 U = 1 + ( 1.5 / ( 1 + adjustBias ) );
5029 small = dx < ( cell * U * std::max( 1, divisions ) * 1e-07 * 3.0 );
5036 cell = 9 + cell / 10;
5037 cell = cell * shrink;
5039 if ( minimumCount > 1 )
5041 cell = cell / minimumCount;
5047 if ( divisions > 1 )
5049 cell = cell / divisions;
5052 if ( cell < 20 * 1e-07 )
5057 const double base = std::pow( 10.0, std::floor( std::log10( cell ) ) );
5059 if ( ( 2 * base ) - cell < h * ( cell - unit ) )
5062 if ( ( 5 * base ) - cell < adjustBias * ( cell - unit ) )
5065 if ( ( 10.0 * base ) - cell < h * ( cell - unit ) )
5072 int start = std::floor( minimum / unit + 1e-07 );
5073 int end = std::ceil( maximum / unit - 1e-07 );
5076 while ( start * unit > minimum + ( 1e-07 * unit ) )
5080 while ( end * unit < maximum - ( 1e-07 * unit ) )
5088 int k = std::floor( 0.5 + end - start );
5089 if ( k < minimumCount )
5091 k = minimumCount - k;
5095 start = start - k / 2 + k % 2;
5099 start = start - k / 2;
5100 end = end + k / 2 + k % 2;
5103 const double minimumBreak = start * unit;
5105 const int count = end - start;
5107 breaks.reserve( count );
5108 for (
int i = 1; i < count + 1; i++ )
5110 breaks.append( minimumBreak + i * unit );
5113 if ( breaks.isEmpty() )
5116 if ( breaks.first() < minimum )
5118 breaks[0] = minimum;
5120 if ( breaks.last() > maximum )
5122 breaks[breaks.count() - 1] = maximum;
5127 if ( minimum < 0.0 && maximum > 0.0 )
5129 QList<double> breaksMinusZero;
5130 for (
int i = 0; i < breaks.count(); i++ )
5132 breaksMinusZero.append( breaks[i] - 0.0 );
5135 for (
int i = 1; i < breaks.count(); i++ )
5137 if ( std::abs( breaksMinusZero[i] ) < std::abs( breaksMinusZero[i - 1] ) )
5140 breaks[posOfMin] = 0.0;
5149 bool roundToUnit =
false;
5152 if ( props.contains( u
"uomScale"_s ) )
5155 scale = props.value( u
"uomScale"_s ).toDouble( &ok );
5164 if ( props.value( u
"uom"_s ) ==
"http://www.opengeospatial.org/se/units/metre"_L1 )
5189 scale = 1 / 0.28 * 25.4;
5212 double rescaled = size * scale;
5217 rescaled = std::round( rescaled );
5224 const double x =
rescaleUom( point.x(), unit, props );
5225 const double y =
rescaleUom( point.y(), unit, props );
5226 return QPointF( x, y );
5231 QVector<qreal> result;
5232 QVector<qreal>::const_iterator it = array.constBegin();
5233 for ( ; it != array.constEnd(); ++it )
5235 result.append(
rescaleUom( *it, unit, props ) );
5242 if ( !props.value( u
"scaleMinDenom"_s, QString() ).toString().isEmpty() )
5244 QDomElement scaleMinDenomElem = doc.createElement( u
"se:MinScaleDenominator"_s );
5245 scaleMinDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( u
"scaleMinDenom"_s ).toString().toDouble() ) ) );
5246 ruleElem.appendChild( scaleMinDenomElem );
5249 if ( !props.value( u
"scaleMaxDenom"_s, QString() ).toString().isEmpty() )
5251 QDomElement scaleMaxDenomElem = doc.createElement( u
"se:MaxScaleDenominator"_s );
5252 scaleMaxDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( u
"scaleMaxDenom"_s ).toString().toDouble() ) ) );
5253 ruleElem.appendChild( scaleMaxDenomElem );
5262 const double parentScaleMinDenom = props.value( u
"scaleMinDenom"_s, u
"0"_s ).toString().toDouble( &ok );
5263 if ( !ok || parentScaleMinDenom <= 0 )
5264 props[u
"scaleMinDenom"_s] = QString::number( mScaleMinDenom );
5266 props[u
"scaleMinDenom"_s] = QString::number( std::max( parentScaleMinDenom, mScaleMinDenom ) );
5272 const double parentScaleMaxDenom = props.value( u
"scaleMaxDenom"_s, u
"0"_s ).toString().toDouble( &ok );
5273 if ( !ok || parentScaleMaxDenom <= 0 )
5274 props[u
"scaleMaxDenom"_s] = QString::number( mScaleMaxDenom );
5276 props[u
"scaleMaxDenom"_s] = QString::number( std::min( parentScaleMaxDenom, mScaleMaxDenom ) );
5284 if ( uom ==
"http://www.opengeospatial.org/se/units/metre"_L1 )
5286 scale = 1.0 / 0.00028;
5288 else if ( uom ==
"http://www.opengeospatial.org/se/units/foot"_L1 )
5290 scale = 304.8 / 0.28;
5297 return size * scale;
5306 SymbolLayerVisitor(
const QSet<QgsSymbolLayerId> &layerIds )
5307 : mSymbolLayerIds( layerIds )
5320 void visitSymbol(
const QgsSymbol *symbol,
const QString &identifier, QVector<int> rootPath )
5324 QVector<int> indexPath = rootPath;
5325 indexPath.append( idx );
5328 if ( mSymbolLayerIds.contains(
QgsSymbolLayerId( mCurrentRuleKey + identifier, indexPath ) ) )
5330 mSymbolLayers.insert( sl );
5336 visitSymbol( subSymbol, identifier, indexPath );
5345 if ( symbolEntity->symbol() )
5347 visitSymbol( symbolEntity->symbol(), leaf.
identifier, {} );
5353 QString mCurrentRuleKey;
5354 const QSet<QgsSymbolLayerId> &mSymbolLayerIds;
5355 QSet<const QgsSymbolLayer *> mSymbolLayers;
5359 SymbolLayerVisitor visitor( symbolLayerIds );
5360 renderer->
accept( &visitor );
5361 return visitor.mSymbolLayers;
5369 SymbolRefreshRateVisitor() {}
5380 void visitSymbol(
const QgsSymbol *symbol )
5397 if ( refreshRate == -1 || ( animatedMarker->frameRate() > refreshRate ) )
5398 refreshRate = animatedMarker->frameRate();
5402 visitSymbol( subSymbol );
5410 if (
QgsSymbol *symbol = qgis::down_cast<const QgsStyleSymbolEntity *>( leaf.
entity )->symbol() )
5412 visitSymbol( symbol );
5418 double refreshRate = -1;
5421 SymbolRefreshRateVisitor visitor;
5422 renderer->
accept( &visitor );
5423 return visitor.refreshRate;
5428 if ( !s || !context )
5454 size = markerSymbol->
size( *context );
5456 else if ( lineSymbol )
5458 size = lineSymbol->
width( *context );
5470 if ( minSize > 0 && size < minSize )
5474 else if ( maxSize > 0 && size > maxSize )
5486 std::unique_ptr< QgsMarkerSymbol > ms( markerSymbol->
clone() );
5487 ms->setSize( size );
5493 else if ( lineSymbol )
5495 std::unique_ptr< QgsLineSymbol > ls( lineSymbol->
clone() );
5496 ls->setWidth( size );
5508 QMap<QString, QgsProperty>::const_iterator paramIt = propertiesMap.constBegin();
5509 for ( ; paramIt != propertiesMap.constEnd(); ++paramIt )
5511 properties.insert( paramIt.key(), paramIt.value().valueAsString( context ) );
5518 angleRad = std::fmod( angleRad, M_PI * 2 );
5522 angleRad += M_PI * 2;
5526 struct rationalTangent
5538 static const QList<rationalTangent> __rationalTangents
5540 { 1, 57, 0.01754206006 },
5541 { 3, 86, 0.03486958155 },
5542 { 1, 19, 0.05258306161 },
5543 { 3, 43, 0.06965457373 },
5544 { 7, 80, 0.08727771295 },
5545 { 2, 19, 0.1048769387 },
5546 { 7, 57, 0.1221951707 },
5547 { 9, 64, 0.1397088743 },
5548 { 13, 82, 0.157228051 },
5549 { 3, 17, 0.174672199 },
5550 { 7, 36, 0.1920480172 },
5551 { 17, 80, 0.209385393 },
5552 { 3, 13, 0.2267988481 },
5553 { 1, 4, 0.2449786631 },
5554 { 26, 97, 0.2618852647 },
5555 { 27, 94, 0.2797041525 },
5556 { 26, 85, 0.2968446734 },
5557 { 13, 40, 0.3142318991 },
5558 { 21, 61, 0.3315541619 },
5559 { 4, 11, 0.3487710036 },
5560 { 38, 99, 0.3664967859 },
5561 { 40, 99, 0.383984624 },
5562 { 31, 73, 0.4015805401 },
5563 { 41, 92, 0.4192323938 },
5564 { 7, 15, 0.4366271598 },
5565 { 20, 41, 0.4538440015 },
5566 { 27, 53, 0.4711662643 },
5567 { 42, 79, 0.4886424026 },
5568 { 51, 92, 0.5061751436 },
5569 { 56, 97, 0.5235757641 },
5570 { 3, 5, 0.5404195003 },
5571 { 5, 8, 0.5585993153 },
5572 { 50, 77, 0.5759185996 },
5573 { 29, 43, 0.5933501462 },
5574 { 7, 10, 0.6107259644 },
5575 { 69, 95, 0.6281701124 },
5576 { 52, 69, 0.6458159195 },
5577 { 25, 32, 0.6632029927 },
5578 { 17, 21, 0.6805212247 },
5579 { 73, 87, 0.6981204504 },
5580 { 73, 84, 0.7154487784 },
5581 { 9, 10, 0.7328151018 },
5582 { 83, 89, 0.7505285818 },
5583 { 28, 29, 0.7678561033 },
5584 { 1, 1, 0.7853981634 },
5585 { 29, 28, 0.8029402235 },
5586 { 89, 83, 0.820267745 },
5587 { 10, 9, 0.837981225 },
5588 { 107, 93, 0.855284165 },
5589 { 87, 73, 0.8726758763 },
5590 { 121, 98, 0.8900374031 },
5591 { 32, 25, 0.9075933341 },
5592 { 69, 52, 0.9249804073 },
5593 { 128, 93, 0.9424647244 },
5594 { 10, 7, 0.9600703624 },
5595 { 43, 29, 0.9774461806 },
5596 { 77, 50, 0.9948777272 },
5597 { 8, 5, 1.012197011 },
5598 { 163, 98, 1.029475114 },
5599 { 168, 97, 1.047174539 },
5600 { 175, 97, 1.064668696 },
5601 { 126, 67, 1.082075603 },
5602 { 157, 80, 1.099534652 },
5603 { 203, 99, 1.117049384 },
5604 { 193, 90, 1.134452855 },
5605 { 146, 65, 1.151936673 },
5606 { 139, 59, 1.169382787 },
5607 { 99, 40, 1.186811703 },
5608 { 211, 81, 1.204257817 },
5609 { 272, 99, 1.221730164 },
5610 { 273, 94, 1.239188479 },
5611 { 277, 90, 1.25664606 },
5612 { 157, 48, 1.274088705 },
5613 { 279, 80, 1.291550147 },
5614 { 362, 97, 1.308990773 },
5615 { 373, 93, 1.326448578 },
5616 { 420, 97, 1.343823596 },
5617 { 207, 44, 1.361353157 },
5618 { 427, 83, 1.378810994 },
5619 { 414, 73, 1.396261926 },
5620 { 322, 51, 1.413716057 },
5621 { 185, 26, 1.431170275 },
5622 { 790, 97, 1.448623034 },
5623 { 333, 35, 1.466075711 },
5624 { 1063, 93, 1.483530284 },
5625 { 1330, 93, 1.500985147 },
5626 { 706, 37, 1.518436297 },
5627 { 315, 11, 1.535889876 },
5628 { 3953, 69, 1.553343002 },
5634 static const QList<rationalTangent> rationalTangents {
5635 { 1, 10, qDegreesToRadians( 5.71059 ) },
5636 { 1, 5, qDegreesToRadians( 11.3099 ) },
5637 { 1, 4, qDegreesToRadians( 14.0362 ) },
5638 { 1, 4, qDegreesToRadians( 18.4349 ) },
5639 { 1, 2, qDegreesToRadians( 26.5651 ) },
5640 { 2, 3, qDegreesToRadians( 33.6901 ) },
5641 { 1, 1, qDegreesToRadians( 45.0 ) },
5642 { 3, 2, qDegreesToRadians( 56.3099 ) },
5643 { 2, 1, qDegreesToRadians( 63.4349 ) },
5644 { 3, 1, qDegreesToRadians( 71.5651 ) },
5645 { 4, 1, qDegreesToRadians( 75.9638 ) },
5646 { 10, 1, qDegreesToRadians( 84.2894 ) },
5649 const int quadrant {
static_cast<int>( angleRad / M_PI_2 ) };
5650 Q_ASSERT( quadrant >= 0 && quadrant <= 3 );
5662 angleRad -= M_PI / 2;
5672 angleRad -= M_PI + M_PI_2;
5693 for (
int idx = 0; idx < rationalTangents.count(); ++idx )
5695 const auto item = rationalTangents.at( idx );
5696 if (
qgsDoubleNear( item.angle, angleRad, 10E-3 ) || item.angle > angleRad )
5703 const rationalTangent bTan { rationalTangents.at( rTanIdx ) };
5704 angleRad = bTan.angle;
5705 const double k { bTan.q * height * width / std::cos( angleRad ) };
5706 const int hcfH { std::gcd( bTan.p * height, bTan.q * width ) };
5707 const int hcfW { std::gcd( bTan.q * height, bTan.p * width ) };
5708 const int W1 {
static_cast<int>( std::round( k / hcfW ) ) };
5709 const int H1 {
static_cast<int>( std::round( k / hcfH ) ) };
5722 angleRad += M_PI / 2;
5735 angleRad += M_PI + M_PI_2;
5748 sl->
setId( generateId() );
5789 maskSl->clearMasks();
5792 if (
QgsSymbol *subSymbol = maskSl->subSymbol() )
5803 if ( clipGeometries.empty() )
5806 if ( bounds.isNull() )
5807 return clipGeometries;
5812 .erase( std::remove_if( clipGeometries.begin(), clipGeometries.end(), [&boundsRect](
const QgsGeometry &geometry ) { return !geometry.boundingBoxIntersects( boundsRect ); } ), clipGeometries.end() );
5814 return clipGeometries;
@ PreferVector
Prefer vector-based rendering, when the result will still be visually near-identical to a raster-base...
MarkerClipMode
Marker clipping modes.
@ CompletelyWithin
Render complete markers wherever the completely fall within the polygon shape.
@ NoClipping
No clipping, render complete markers.
@ Shape
Clip to polygon shape.
@ CentroidWithin
Render complete markers wherever their centroid falls within the polygon shape.
LineClipMode
Line clipping modes.
@ NoClipping
Lines are not clipped, will extend to shape's bounding box.
@ ClipPainterOnly
Applying clipping on the painter only (i.e. line endpoints will coincide with polygon bounding box,...
@ ClipToIntersection
Clip lines to intersection with polygon shape (slower) (i.e. line endpoints will coincide with polygo...
ScaleMethod
Scale methods.
@ ScaleDiameter
Calculate scale by the diameter.
@ ScaleArea
Calculate scale by the area.
QFlags< SymbolLayerUserFlag > SymbolLayerUserFlags
Symbol layer user flags.
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
JoinStyle
Join styles for buffers.
@ Bevel
Use beveled joins.
@ Round
Use rounded joins.
@ Miter
Use mitered joins.
RenderUnit
Rendering size units.
@ Percentage
Percentage of another measurement (e.g., canvas size, feature size).
@ Millimeters
Millimeters.
@ Points
Points (e.g., for font sizes).
@ Unknown
Mixed or unknown units.
@ MetersInMapUnits
Meters value as Map units.
EndCapStyle
End cap styles for buffers.
@ Flat
Flat cap (in line with start/end of line).
@ Square
Square cap (extends past start/end of line by buffer distance).
@ RenderSymbolPreview
The render is for a symbol preview only and map based properties may not be available,...
@ Antialiasing
Use antialiasing while drawing.
@ HighQualityImageTransforms
Enable high quality image transformations, which results in better appearance of scaled or rotated ra...
VertexMarkerType
Editing vertex markers, used for showing vertices during a edit operation.
@ SemiTransparentCircle
Semi-transparent circle marker.
QFlags< SymbolRenderHint > SymbolRenderHints
Symbol render hints.
QFlags< SymbolFlag > SymbolFlags
Symbol flags.
@ RendererShouldUseSymbolLevels
If present, indicates that a QgsFeatureRenderer using the symbol should use symbol levels for best re...
@ MultiPolygon
MultiPolygon.
@ MultiLineString
MultiLineString.
SymbolCoordinateReference
Symbol coordinate reference modes.
@ Feature
Relative to feature/shape being rendered.
@ Viewport
Relative to the whole viewport/output device.
Abstract base class for all geometries.
vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry.
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
const_part_iterator const_parts_end() const
Returns STL-style iterator pointing to the imaginary const part after the last part of the geometry.
vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
const_part_iterator const_parts_begin() const
Returns STL-style iterator pointing to the const first part of the geometry.
virtual bool writeXml(QDomElement &collectionElem, const QgsPropertiesDefinition &definitions) const
Writes the current state of the property collection into an XML element.
Animated marker symbol layer class.
static QgsPaintEffectRegistry * paintEffectRegistry()
Returns the application's paint effect registry, used for managing paint effects.
static QgsSymbolLayerRegistry * symbolLayerRegistry()
Returns the application's symbol layer registry, used for managing symbol layers.
static QStringList svgPaths()
Returns the paths to svg directories.
HeadType
Possible head types.
ArrowType
Possible arrow types.
static QString typeString()
Returns the string identifier for QgsColorBrewerColorRamp.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Returns a new QgsColorBrewerColorRamp color ramp created using the properties encoded in a string map...
Abstract base class for color ramps.
virtual QColor color(double value) const =0
Returns the color corresponding to a specified value.
virtual QVariantMap properties() const =0
Returns a string map containing all the color ramp's properties.
virtual QString type() const =0
Returns a string representing the color ramp type.
static QColor colorFromString(const QString &string)
Decodes a string into a color value.
static QString colorToString(const QColor &color)
Encodes a color into a string value.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates the symbol layer.
static QString typeString()
Returns the string identifier for QgsCptCityColorRamp.
Curve polygon geometry type.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
Abstract base class for curved geometry type.
virtual QgsLineString * curveToLine(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const =0
Returns a new line string geometry corresponding to a segmentized approximation of the curve.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
bool hasFeature() const
Returns true if the context has a feature associated with it.
An expression node which takes its value from a feature's field.
Abstract base class for all nodes that can appear in an expression.
virtual QgsExpressionNode::NodeType nodeType() const =0
Gets the type of this node.
Handles parsing and evaluation of expressions (formerly called "search strings").
QString expression() const
Returns the original, unmodified expression string.
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
QString parserErrorString() const
Returns parser error.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes).
const QgsExpressionNode * rootNode() const
Returns the root node of the expression.
Abstract base class for all 2D vector feature renderers.
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
Abstract base class for fill symbol layers.
static void pointOnLineWithDistance(double x1, double y1, double x2, double y2, double distance, double &x, double &y, double *z1=nullptr, double *z2=nullptr, double *z=nullptr, double *m1=nullptr, double *m2=nullptr, double *m=nullptr)
Calculates the point a specified distance from (x1, y1) toward a second point (x2,...
static double normalizedAngle(double angle)
Ensures that an angle is in the range 0 <= angle < 2 pi.
A geometry is the spatial representation of a feature.
QgsMultiPolygonXY asMultiPolygon() const
Returns the contents of the geometry as a multi-polygon.
QgsGeometry offsetCurve(double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit) const
Returns an offset line at a given distance and side from an input line.
QgsGeometry pointOnSurface() const
Returns a point guaranteed to lie on the surface of a geometry.
static QgsGeometry fromPolylineXY(const QgsPolylineXY &polyline)
Creates a new LineString geometry from a list of QgsPointXY points.
QgsPolygonXY asPolygon() const
Returns the contents of the geometry as a polygon.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsPolylineXY asPolyline() const
Returns the contents of the geometry as a polyline.
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
Qgis::GeometryOperationResult addRing(const QVector< QgsPointXY > &ring)
Adds a new ring to this geometry.
QgsMultiPolylineXY asMultiPolyline() const
Returns the contents of the geometry as a multi-linestring.
static QgsGeometry fromPolygonXY(const QgsPolygonXY &polygon)
Creates a new geometry from a QgsPolygonXY.
QgsGeometry buffer(double distance, int segments) const
Returns a buffer region around this geometry having the given width and with a specified number of se...
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.).
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsColorRamp from a map of properties.
static QString typeString()
Returns the string identifier for QgsGradientColorRamp.
Represents a patch shape for use in map legends.
static QString typeString()
Returns the string identifier for QgsLimitedRandomColorRamp.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Returns a new QgsLimitedRandomColorRamp color ramp created using the properties encoded in a string m...
Line string geometry type, with support for z-dimension and m-values.
const double * yData() const
Returns a const pointer to the y vertex data.
const double * xData() const
Returns a const pointer to the x vertex data.
int numPoints() const override
Returns the number of points in the curve.
Abstract base class for line symbol layers.
const QgsMapUnitScale & widthMapUnitScale() const
@ AllRings
Render both exterior and interior rings.
RenderRingFilter ringFilter() const
Returns the line symbol layer's ring filter, which controls which rings are rendered when the line sy...
virtual double width() const
Returns the estimated width for the line symbol layer.
double offset() const
Returns the line's offset.
Qgis::RenderUnit widthUnit() const
Returns the units for the line's width.
A line symbol type, for rendering LineString and MultiLineString geometries.
QgsLineSymbol * clone() const override
Returns a deep copy of this symbol.
double width() const
Returns the estimated width for the whole symbol, which is the maximum width of all marker symbol lay...
Base class for all map layer types.
Struct for storing maximum and minimum scales for measurements in map units.
bool minSizeMMEnabled
Whether the minimum size in mm should be respected.
double maxScale
The maximum scale, or 0.0 if unset.
double minScale
The minimum scale, or 0.0 if unset.
double maxSizeMM
The maximum size in millimeters, or 0.0 if unset.
bool maxSizeMMEnabled
Whether the maximum size in mm should be respected.
double minSizeMM
The minimum size in millimeters, or 0.0 if unset.
A marker symbol type, for rendering Point and MultiPoint geometries.
double size() const
Returns the estimated size for the whole symbol, which is the maximum size of all marker symbol layer...
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
Special symbol layer that uses its sub symbol as a selective mask.
static QDomElement elseFilterExpression(QDomDocument &doc)
Creates an ElseFilter from doc.
static QDomElement expressionToOgcExpression(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr, bool requiresFilterElement=false)
Creates an OGC expression XML element from the exp expression with default values for the geometry na...
static QDomElement expressionToOgcFilter(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr)
Creates OGC filter XML element.
static QgsExpression * expressionFromOgcFilter(const QDomElement &element, QgsVectorLayer *layer=nullptr)
Parse XML with OGC filter into QGIS expression.
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
virtual bool saveProperties(QDomDocument &doc, QDomElement &element) const
Saves the current state of the effect to a DOM element.
Resolves relative paths into absolute paths and vice versa.
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
void setX(double x)
Sets the x value of the point.
static QString typeString()
Returns the string identifier for QgsPresetSchemeColorRamp.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Returns a new QgsPresetSchemeColorRamp color ramp created using the properties encoded in a string ma...
A grouped map of multiple QgsProperty objects, each referenced by an integer key value.
QSet< int > propertyKeys() const final
Returns a list of property keys contained within the collection.
QgsProperty property(int key) const final
Returns a matching property from the collection, if one exists.
A store for object properties.
bool isProjectColor() const
Returns true if the property is set to a linked project color.
bool isActive() const
Returns whether the property is currently active.
void setActive(bool active)
Sets whether the property is currently active.
A container for the context for various read/write operations on objects.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
A rectangle specified with double values.
Contains information about the context of a rendering operation.
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
void setDevicePixelRatio(float ratio)
Sets the device pixel ratio.
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
QgsExpressionContext & expressionContext()
Gets the expression context.
void setRasterizedRenderingPolicy(Qgis::RasterizedRenderingPolicy policy)
Sets the policy controlling when rasterisation of content during renders is permitted.
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected).
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
QVector< QgsGeometry > symbolLayerClipGeometries(const QString &symbolLayerId) const
Returns clipping geometries to be applied to the symbolLayer before rendering.
static QgsRenderContext fromQPainter(QPainter *painter)
Creates a default render context given a pixel based QPainter destination.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
A fill symbol layer which fills polygons with a repeated SVG file.
Stores properties relating to a screen.
double devicePixelRatio() const
Returns the ratio between physical pixels and device-independent pixels for the screen.
bool isValid() const
Returns true if the properties are valid.
void updateRenderContextForScreen(QgsRenderContext &context) const
Updates the settings in a render context to match the screen settings.
Renders polygons using a single fill and stroke color.
void setStrokeWidthMapUnitScale(const QgsMapUnitScale &scale)
void setStrokeWidthUnit(Qgis::RenderUnit unit)
Sets the units for the width of the fill's stroke.
void setPenJoinStyle(Qt::PenJoinStyle style)
void setStrokeWidth(double strokeWidth)
void setStrokeStyle(Qt::PenStyle strokeStyle)
void setStrokeColor(const QColor &strokeColor) override
Sets the stroke color for the symbol layer.
A simple line symbol layer, which renders lines using a line in a variety of styles (e....
bool tweakDashPatternOnCorners() const
Returns true if dash patterns tweaks should be applied on sharp corners, to ensure that a double-leng...
Qt::PenJoinStyle penJoinStyle() const
Returns the pen join style used to render the line (e.g.
double trimDistanceStart() const
Returns the trim distance for the start of the line, which dictates a length from the start of the li...
double trimDistanceEnd() const
Returns the trim distance for the end of the line, which dictates a length from the end of the line a...
bool useCustomDashPattern() const
Returns true if the line uses a custom dash pattern.
Qt::PenStyle penStyle() const
Returns the pen style used to render the line (e.g.
double dashPatternOffset() const
Returns the dash pattern offset, which dictates how far along the dash pattern the pattern should sta...
bool drawInsidePolygon() const
Returns true if the line should only be drawn inside polygons, and any portion of the line which fall...
bool alignDashPattern() const
Returns true if dash patterns should be aligned to the start and end of lines, by applying subtle twe...
Holds SLD export options and other information related to SLD export of a QGIS layer style.
void pushWarning(const QString &warning)
Pushes a warning message generated during the conversion.
void pushError(const QString &error)
Pushes a error message generated during the conversion.
virtual QgsStyle::StyleEntity type() const =0
Returns the type of style entity.
An interface for classes which can visit style entity (e.g.
@ SymbolRule
Rule based symbology or label child rule.
A symbol entity for QgsStyle databases.
bool isAnimated() const
Returns true if the symbol is animated.
double frameRate() const
Returns the symbol animation frame rate (in frames per second).
Contains settings relating to symbol buffers, which draw a "halo" effect around the symbol.
We may need stable references to symbol layers, when pointers to symbol layers are not usable (when a...
std::unique_ptr< QgsSymbolLayer > createSymbolLayerFromSld(const QString &name, QDomElement &element) const
create a new instance of symbol layer given symbol layer name and SLD
void resolvePaths(const QString &name, QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving) const
Resolve paths in properties of a particular symbol layer.
void resolveFonts(const QString &name, QVariantMap &properties, const QgsReadWriteContext &context) const
Resolve fonts from the properties of a particular symbol layer.
std::unique_ptr< QgsSymbolLayer > createSymbolLayer(const QString &name, const QVariantMap &properties=QVariantMap()) const
create a new instance of symbol layer given symbol layer name and properties
static bool externalMarkerFromSld(QDomElement &element, QString &path, QString &format, int &markIndex, QColor &color, double &size)
static QColor parseColor(const QString &colorStr, bool strictEval=false)
Attempts to parse a string as a color using a variety of common formats, including hex codes,...
static bool rotationFromSldElement(QDomElement &element, QString &rotationFunc)
static void createAnchorPointElement(QDomDocument &doc, QDomElement &element, QPointF anchor)
Creates a SE 1.1 anchor point element as a child of the specified element.
static void sortVariantList(QList< QVariant > &list, Qt::SortOrder order)
Sorts the passed list in requested order.
static Qgis::MarkerClipMode decodeMarkerClipMode(const QString &string, bool *ok=nullptr)
Decodes a string representing a marker clip mode.
static QPicture symbolLayerPreviewPicture(const QgsSymbolLayer *layer, Qgis::RenderUnit units, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::SymbolType parentSymbolType=Qgis::SymbolType::Hybrid)
Draws a symbol layer preview to a QPicture.
static bool hasExternalGraphic(QDomElement &element)
Checks if element contains an ExternalGraphic element with format "image/svg+xml".
static QString encodePenStyle(Qt::PenStyle style)
static bool needMarkerLine(QDomElement &element)
static QVector< qreal > decodeSldRealVector(const QString &s)
static bool needLinePatternFill(QDomElement &element)
static std::unique_ptr< QgsSymbol > symbolFromMimeData(const QMimeData *data)
Attempts to parse mime data as a symbol.
static void clearSymbolLayerIds(QgsSymbol *symbol)
Remove recursively unique id from all symbol symbol layers and set an empty string instead.
static QString encodeSldBrushStyle(Qt::BrushStyle style)
static Qt::PenJoinStyle decodePenJoinStyle(const QString &str)
static QgsArrowSymbolLayer::HeadType decodeArrowHeadType(const QVariant &value, bool *ok=nullptr)
Decodes a value representing an arrow head type.
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
static Q_DECL_DEPRECATED QSet< const QgsSymbolLayer * > toSymbolLayerPointers(const QgsFeatureRenderer *renderer, const QSet< QgsSymbolLayerId > &symbolLayerIds)
Converts a set of symbol layer id to a set of pointers to actual symbol layers carried by the feature...
static QVariant colorRampToVariant(const QString &name, QgsColorRamp *ramp)
Saves a color ramp to a QVariantMap, wrapped in a QVariant.
static void applyScaleDependency(QDomDocument &doc, QDomElement &ruleElem, QVariantMap &props)
Checks if the properties contain scaleMinDenom and scaleMaxDenom, if available, they are added into t...
static QgsStringMap evaluatePropertiesMap(const QMap< QString, QgsProperty > &propertiesMap, const QgsExpressionContext &context)
Evaluates a map of properties using the given context and returns a variant map with evaluated expres...
static void drawVertexMarker(double x, double y, QPainter &p, Qgis::VertexMarkerType type, int markerSize)
Draws a vertex symbol at (painter) coordinates x, y.
static Q_DECL_DEPRECATED bool createExpressionElement(QDomDocument &doc, QDomElement &element, const QString &function)
Creates a OGC Expression element based on the provided function expression.
static bool displacementFromSldElement(QDomElement &element, QPointF &offset)
static bool hasWellKnownMark(QDomElement &element)
static std::unique_ptr< QgsColorRamp > loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
static QString getSvgParametricPath(const QString &basePath, const QColor &fillColor, const QColor &strokeColor, double strokeWidth)
Encodes a reference to a parametric SVG into a path with parameters according to the SVG Parameters s...
static Q_DECL_DEPRECATED bool createFunctionElement(QDomDocument &doc, QDomElement &element, const QString &function)
Creates an OGC function element.
static std::unique_ptr< QgsSymbol > restrictedSizeSymbol(const QgsSymbol *s, double minSize, double maxSize, QgsRenderContext *context, double &width, double &height, bool *ok=nullptr)
Creates a new symbol with size restricted to min/max size if original size is out of min/max range.
static QColor decodeColor(const QString &str)
static std::unique_ptr< QgsSymbolLayer > loadSymbolLayer(QDomElement &element, const QgsReadWriteContext &context)
Reads and returns symbol layer from XML. Caller is responsible for deleting the returned object.
static bool onlineResourceFromSldElement(QDomElement &element, QString &path, QString &format)
static QPointF polygonCentroid(const QPolygonF &points)
Calculate the centroid point of a QPolygonF.
static QIcon colorRampPreviewIcon(QgsColorRamp *ramp, QSize size, int padding=0)
Returns an icon preview for a color ramp.
static QString encodeBrushStyle(Qt::BrushStyle style)
static QString svgSymbolPathToName(const QString &path, const QgsPathResolver &pathResolver)
Determines an SVG symbol's name from its path.
static bool needRasterMarker(const QDomElement &element)
Checks if element contains an ExternalGraphic element that should translate to a raster marker.
static QPixmap colorRampPreviewPixmap(QgsColorRamp *ramp, QSize size, int padding=0, Qt::Orientation direction=Qt::Horizontal, bool flipDirection=false, bool drawTransparentBackground=true)
Returns a pixmap preview for a color ramp.
static QString encodeSldAlpha(int alpha)
static void externalGraphicToSld(QDomDocument &doc, QDomElement &element, const QString &path, const QString &mime, const QColor &color, double size=-1)
static QPointF polygonPointOnSurface(const QPolygonF &points, const QVector< QPolygonF > *rings=nullptr)
Calculate a point on the surface of a QPolygonF.
static void blurImageInPlace(QImage &image, QRect rect, int radius, bool alphaOnly)
Blurs an image in place, e.g. creating Qt-independent drop shadows.
static QList< double > prettyBreaks(double minimum, double maximum, int classes)
Computes a sequence of about 'classes' equally spaced round values which cover the range of values fr...
static QPointF toPoint(const QVariant &value, bool *ok=nullptr)
Converts a value to a point.
static void premultiplyColor(QColor &rgb, int alpha)
Converts a QColor into a premultiplied ARGB QColor value using a specified alpha value.
static void saveProperties(QVariantMap props, QDomDocument &doc, QDomElement &element)
Saves the map of properties to XML.
static void multiplyImageOpacity(QImage *image, qreal opacity)
Multiplies opacity of image pixel values with a (global) transparency value.
static bool functionFromSldElement(QDomElement &element, QString &function)
static bool saveColorsToGpl(QFile &file, const QString &paletteName, const QgsNamedColorList &colors)
Exports colors to a gpl GIMP palette file.
static std::unique_ptr< QgsSymbolLayer > createFillLayerFromSld(QDomElement &element)
Creates a new fill layer from a SLD DOM element.
static QColor parseColorWithAlpha(const QString &colorStr, bool &containsAlpha, bool strictEval=false)
Attempts to parse a string as a color using a variety of common formats, including hex codes,...
static bool hasSldSymbolizer(const QDomElement &element)
Returns true if a DOM element contains an SLD Symbolizer element.
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
static QSizeF toSize(const QVariant &value, bool *ok=nullptr)
Converts a value to a size.
static double rescaleUom(double size, Qgis::RenderUnit unit, const QVariantMap &props)
Rescales the given size based on the uomScale found in the props, if any is found,...
static bool needEllipseMarker(QDomElement &element)
static std::unique_ptr< QgsSymbolLayer > createMarkerLayerFromSld(QDomElement &element)
Creates a new marker layer from a SLD DOM element.
static QgsNamedColorList colorListFromMimeData(const QMimeData *data)
Attempts to parse mime data as a list of named colors.
static void clearSymbolLayerMasks(QgsSymbol *symbol)
Remove recursively masks from all symbol symbol layers.
static bool isSharpCorner(QPointF p1, QPointF p2, QPointF p3)
Returns true if the angle formed by the line p1 - p2 - p3 forms a "sharp" corner.
static QString ogrFeatureStylePen(double width, double mmScaleFactor, double mapUnitsScaleFactor, const QColor &c, Qt::PenJoinStyle joinStyle=Qt::MiterJoin, Qt::PenCapStyle capStyle=Qt::FlatCap, double offset=0.0, const QVector< qreal > *dashPattern=nullptr)
Create ogr feature style string for pen.
static Qt::PenCapStyle decodePenCapStyle(const QString &str)
static double rendererFrameRate(const QgsFeatureRenderer *renderer)
Calculates the frame rate (in frames per second) at which the given renderer must be redrawn.
static QgsStringMap getSvgParameterList(QDomElement &element)
static bool needSvgFill(QDomElement &element)
static bool createSymbolLayerListFromSld(QDomElement &element, Qgis::GeometryType geomType, QList< QgsSymbolLayer * > &layers)
Creates a symbol layer list from a DOM element.
static bool externalGraphicFromSld(QDomElement &element, QString &path, QString &mime, QColor &color, double &size)
static Q_DECL_DEPRECATED void parametricSvgToSld(QDomDocument &doc, QDomElement &graphicElem, const QString &path, const QColor &fillColor, double size, const QColor &strokeColor, double strokeWidth)
Encodes a reference to a parametric SVG into SLD, as a succession of parametric SVG using URL paramet...
static QIcon symbolLayerPreviewIcon(const QgsSymbolLayer *layer, Qgis::RenderUnit u, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::SymbolType parentSymbolType=Qgis::SymbolType::Hybrid, QgsMapLayer *mapLayer=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Draws a symbol layer preview to an icon.
static QString encodeSldLineCapStyle(Qt::PenCapStyle style)
static QString encodeSldUom(Qgis::RenderUnit unit, double *scaleFactor)
Encodes a render unit into an SLD unit of measure string.
static QList< QList< QPolygonF > > toQPolygonF(const QgsGeometry &geometry, Qgis::SymbolType type)
Converts a geometry to a set of QPolygonF objects representing how the geometry should be drawn for a...
static std::unique_ptr< QgsSymbol > loadSymbol(const QDomElement &element, const QgsReadWriteContext &context)
Attempts to load a symbol from a DOM element.
static QVector< qreal > decodeRealVector(const QString &s)
static bool lineFromSld(QDomElement &element, Qt::PenStyle &penStyle, QColor &color, double &width, Qt::PenJoinStyle *penJoinStyle=nullptr, Qt::PenCapStyle *penCapStyle=nullptr, QVector< qreal > *customDashPattern=nullptr, double *dashOffset=nullptr)
static QPainter::CompositionMode decodeBlendMode(const QString &s)
static Qgis::ScaleMethod decodeScaleMethod(const QString &str)
Decodes a symbol scale method from a string.
static Q_DECL_DEPRECATED void createOpacityElement(QDomDocument &doc, QDomElement &element, const QString &alphaFunc)
Creates SLD opacity element.
static std::unique_ptr< QgsSymbolLayer > createLineLayerFromSld(QDomElement &element)
Creates a new line layer from a SLD DOM element.
static QString ogrFeatureStyleBrush(const QColor &fillColr)
Create ogr feature style string for brush.
static bool pointInPolygon(const QPolygonF &points, QPointF point)
Calculate whether a point is within of a QPolygonF.
static QStringList listSvgFiles()
Returns a list of all available svg files.
static QString encodeLineClipMode(Qgis::LineClipMode mode)
Encodes a line clip mode to a string.
static QPixmap symbolPreviewPixmap(const QgsSymbol *symbol, QSize size, int padding=0, QgsRenderContext *customContext=nullptr, bool selected=false, const QgsExpressionContext *expressionContext=nullptr, const QgsLegendPatchShape *shape=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Returns a pixmap preview for a color ramp.
static bool convertPolygonSymbolizerToPointMarker(QDomElement &element, QList< QgsSymbolLayer * > &layerList)
Converts a polygon symbolizer element to a list of marker symbol layers.
static Qgis::LineClipMode decodeLineClipMode(const QString &string, bool *ok=nullptr)
Decodes a string representing a line clip mode.
static bool needSvgMarker(const QDomElement &element)
Checks if element contains an ExternalGraphic element that should translate to an SVG marker.
static QStringList listSvgFilesAt(const QString &directory)
Returns a list of svg files at the specified directory.
static bool needFontMarker(QDomElement &element)
static QString encodePenCapStyle(Qt::PenCapStyle style)
static QPointF pointOnLineWithDistance(QPointF startPoint, QPointF directionPoint, double distance)
Returns a point on the line from startPoint to directionPoint that is a certain distance away from th...
static QFont::Style decodeSldFontStyle(const QString &str)
static QSize tileSize(int width, int height, double &angleRad)
Calculate the minimum size in pixels of a symbol tile given the symbol width and height and the symbo...
static QString fieldOrExpressionFromExpression(QgsExpression *expression)
Returns a field name if the whole expression is just a name of the field .
static bool opacityFromSldElement(QDomElement &element, QString &alphaFunc)
static QString encodeSldFontWeight(int weight)
static Q_DECL_DEPRECATED void externalMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &path, const QString &format, int *markIndex=nullptr, const QColor &color=QColor(), double size=-1)
Exports a marker to an SLD definition.
static QMimeData * colorListToMimeData(const QgsNamedColorList &colorList, bool allFormats=true)
Creates mime data from a list of named colors.
static Qt::BrushStyle decodeBrushStyle(const QString &str)
static QVector< QgsGeometry > collectSymbolLayerClipGeometries(const QgsRenderContext &context, const QString &symbolLayerId, const QRectF &bounds)
Returns a list of the symbol layer clip geometries to be used for the symbol layer with the specified...
static Qt::PenCapStyle decodeSldLineCapStyle(const QString &str)
static QgsNamedColorList importColorsFromGpl(QFile &file, bool &ok, QString &name)
Imports colors from a gpl GIMP palette file.
static QString encodeSize(QSizeF size)
Encodes a QSizeF to a string.
static QDomElement createVendorOptionElement(QDomDocument &doc, const QString &name, const QString &value)
static double sizeInPixelsFromSldUom(const QString &uom, double size)
Returns the size scaled in pixels according to the uom attribute.
static void appendPolyline(QPolygonF &target, const QPolygonF &line)
Appends a polyline line to an existing target polyline.
static bool wellKnownMarkerFromSld(QDomElement &element, QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle, double &strokeWidth, double &size)
Extracts properties from an SLD marker definition.
static void mergeScaleDependencies(double mScaleMinDenom, double mScaleMaxDenom, QVariantMap &props)
Merges the local scale limits, if any, with the ones already in the map, if any.
static QString colorToName(const QColor &color)
Returns a friendly display name for a color.
static int decodeSldAlpha(const QString &str)
static QString encodeSldLineJoinStyle(Qt::PenJoinStyle style)
static void createDisplacementElement(QDomDocument &doc, QDomElement &element, QPointF offset)
static QString svgSymbolNameToPath(const QString &name, const QgsPathResolver &pathResolver)
Determines an SVG symbol's path from its name.
static void drawStippledBackground(QPainter *painter, QRect rect)
static QList< QColor > parseColorList(const QString &colorStr)
Attempts to parse a string as a list of colors using a variety of common formats, including hex codes...
static QString encodeColor(const QColor &color)
static Qt::PenJoinStyle decodeSldLineJoinStyle(const QString &str)
static QVariantMap parseProperties(const QDomElement &element)
Parses the properties from XML and returns a map.
static bool fillFromSld(QDomElement &element, Qt::BrushStyle &brushStyle, QColor &color)
static Qgis::EndCapStyle penCapStyleToEndCapStyle(Qt::PenCapStyle style)
Converts a Qt pen cap style to a QGIS end cap style.
static QMimeData * symbolToMimeData(const QgsSymbol *symbol)
Creates new mime data from a symbol.
static QString encodeSldFontStyle(QFont::Style style)
static QColor colorFromMimeData(const QMimeData *data, bool &hasAlpha)
Attempts to parse mime data as a color.
static int decodeSldFontWeight(const QString &str)
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
static Q_DECL_DEPRECATED void fillToSld(QDomDocument &doc, QDomElement &element, Qt::BrushStyle brushStyle, const QColor &color=QColor())
Exports fill details to an SLD element.
static double polylineLength(const QPolygonF &polyline)
Returns the total length of a polyline.
static QDomElement saveColorRamp(const QString &name, const QgsColorRamp *ramp, QDomDocument &doc)
Encodes a color ramp's settings to an XML element.
static Qgis::RenderUnit decodeSldUom(const QString &str, double *scaleFactor=nullptr)
Decodes a SLD unit of measure string to a render unit.
static Q_DECL_DEPRECATED void createGeometryElement(QDomDocument &doc, QDomElement &element, const QString &geomFunc)
Creates an SLD geometry element.
static QgsArrowSymbolLayer::ArrowType decodeArrowType(const QVariant &value, bool *ok=nullptr)
Decodes a value representing an arrow type.
static void clearSymbolMap(QgsSymbolMap &symbols)
static Qt::BrushStyle decodeSldBrushStyle(const QString &str)
static void resetSymbolLayerIds(QgsSymbol *symbol)
Regenerate recursively unique id from all symbol symbol layers.
static double estimateMaxSymbolBleed(QgsSymbol *symbol, const QgsRenderContext &context)
Returns the maximum estimated bleed for the symbol.
static Q_DECL_DEPRECATED void wellKnownMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &name, const QColor &color, const QColor &strokeColor, Qt::PenStyle strokeStyle, double strokeWidth=-1, double size=-1)
Exports a marker to SLD.
static QString symbolProperties(QgsSymbol *symbol)
Returns a string representing the symbol.
static bool geometryFromSldElement(QDomElement &element, QString &geomFunc)
static QString encodeScaleMethod(Qgis::ScaleMethod scaleMethod)
Encodes a symbol scale method to a string.
static void createOnlineResourceElement(QDomDocument &doc, QDomElement &element, const QString &path, const QString &format)
static Qt::PenStyle decodePenStyle(const QString &str)
static Q_DECL_DEPRECATED void createRotationElement(QDomDocument &doc, QDomElement &element, const QString &rotationFunc)
Creates SLD rotation element.
static Qgis::SymbolCoordinateReference decodeCoordinateReference(const QString &string, bool *ok=nullptr)
Decodes a string representing a symbol coordinate reference mode.
static QgsSymbolMap loadSymbols(QDomElement &element, const QgsReadWriteContext &context)
Reads a collection of symbols from XML and returns them in a map. Caller is responsible for deleting ...
static QString encodePoint(QPointF point)
Encodes a QPointF to a string.
static Q_DECL_DEPRECATED void labelTextToSld(QDomDocument &doc, QDomElement &element, const QString &label, const QFont &font, const QColor &color=QColor(), double size=-1)
Exports label text to SLD.
static QDomElement saveSymbols(QgsSymbolMap &symbols, const QString &tagName, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a collection of symbols to XML with specified tagName for the top-level element.
static std::unique_ptr< QgsExpression > fieldOrExpressionToExpression(const QString &fieldOrExpression)
Returns a new valid expression instance for given field or expression string.
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
static QgsStringMap getVendorOptionList(QDomElement &element)
static Qgis::JoinStyle penJoinStyleToJoinStyle(Qt::PenJoinStyle style)
Converts a Qt pen joinstyle to a QGIS join style.
static QIcon symbolPreviewIcon(const QgsSymbol *symbol, QSize size, int padding=0, QgsLegendPatchShape *shape=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Returns an icon preview for a color ramp.
static QMimeData * colorToMimeData(const QColor &color)
Creates mime data from a color.
static bool condenseFillAndOutline(QgsFillSymbolLayer *fill, QgsLineSymbolLayer *outline)
Attempts to condense a fill and outline layer, by moving the outline layer to the fill symbol's strok...
static QPointF decodePoint(const QString &string)
Decodes a QSizeF from a string.
static QPolygonF polylineSubstring(const QPolygonF &polyline, double startOffset, double endOffset)
Returns the substring of a polyline which starts at startOffset from the beginning of the line and en...
static bool needPointPatternFill(QDomElement &element)
static QString encodeSldRealVector(const QVector< qreal > &v)
static QString encodeCoordinateReference(Qgis::SymbolCoordinateReference coordinateReference)
Encodes a symbol coordinate reference mode to a string.
static bool needRasterImageFill(QDomElement &element)
Checks if element contains a graphic fill with a raster image of type PNG, JPEG or GIF.
static QDomElement createSvgParameterElement(QDomDocument &doc, const QString &name, const QString &value)
static QString encodeMarkerClipMode(Qgis::MarkerClipMode mode)
Encodes a marker clip mode to a string.
static void lineToSld(QDomDocument &doc, QDomElement &element, Qt::PenStyle penStyle, const QColor &color, QgsSldExportContext &context, double width=-1, const Qt::PenJoinStyle *penJoinStyle=nullptr, const Qt::PenCapStyle *penCapStyle=nullptr, const QVector< qreal > *customDashPattern=nullptr, double dashOffset=0.0)
static QSizeF decodeSize(const QString &string)
Decodes a QSizeF from a string.
static bool hasExternalGraphicV2(const QDomElement &element, const QString format=QString())
Checks if element contains an ExternalGraphic element, if the optional format is specified it will al...
static QString encodeRealVector(const QVector< qreal > &v)
Abstract base class for symbol layers.
virtual QgsSymbolLayer * clone() const =0
Shall be reimplemented by subclasses to create a deep copy of the instance.
virtual bool setSubSymbol(QgsSymbol *symbol)
Sets layer's subsymbol. takes ownership of the passed symbol.
void setId(const QString &id)
Set symbol layer identifier This id has to be unique in the whole project.
bool isLocked() const
Returns true if the symbol layer colors are locked and the layer will ignore any symbol-level color c...
Property
Data definable properties.
virtual double estimateMaxBleed(const QgsRenderContext &context) const
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the layer.
QString selectiveMaskingSourceSetId() const
Returns the selective masking source set ID for this symbol layer.
virtual QVariantMap properties() const =0
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
bool enabled() const
Returns true if symbol layer is enabled and will be drawn.
virtual QString layerType() const =0
Returns a string that represents this layer type.
int renderingPass() const
Specifies the rendering pass in which this symbol layer should be rendered.
QString id() const
Returns symbol layer identifier This id is unique in the whole project.
virtual QgsSymbol * subSymbol()
Returns the symbol's sub symbol, if present.
Qgis::SymbolLayerUserFlags userFlags() const
Returns user-controlled flags which control the symbol layer's behavior.
virtual QColor color() const
Returns the "representative" color of the symbol layer.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol layer property definitions.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
virtual bool hasDataDefinedProperties() const
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
Encapsulates the context in which a symbol is being rendered.
void setOriginalGeometryType(Qgis::GeometryType type)
Sets the geometry type for the original feature geometry being rendered.
Abstract base class for all rendered symbols.
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol's property collection, used for data defined overrides.
QgsSymbolAnimationSettings & animationSettings()
Returns a reference to the symbol animation settings.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol property definitions.
Qgis::SymbolFlags flags() const
Returns flags for the symbol.
qreal opacity() const
Returns the opacity for the symbol.
bool clipFeaturesToExtent() const
Returns whether features drawn by the symbol will be clipped to the render context's extent.
QgsSymbolBufferSettings * bufferSettings()
Returns the symbol buffer settings, which control an optional "halo" effect around the symbol.
bool hasDataDefinedProperties() const
Returns whether the symbol utilizes any data defined properties.
QgsSymbolLayerList symbolLayers() const
Returns the list of symbol layers contained in the symbol.
Qgis::RenderUnit extentBufferSizeUnit() const
Returns the units for the buffer size.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
QColor color() const
Returns the symbol's color.
Qgis::SymbolType type() const
Returns the symbol's type.
double extentBuffer() const
Returns the symbol's extent buffer.
bool forceRHR() const
Returns true if polygon features drawn by the symbol will be reoriented to follow the standard right-...
static Q_INVOKABLE Qgis::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
static Qgis::GeometryType geometryType(Qgis::WkbType type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement.
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement.
QList< QPair< QColor, QString > > QgsNamedColorList
List of colors paired with a friendly display name identifying the color.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsVariantLessThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is less than the second.
bool qgsVariantGreaterThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is greater than the second.
#define Q_NOWARN_DEPRECATED_POP
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
QString qgsFlagValueToKeys(const T &value, bool *returnOk=nullptr)
Returns the value for the given keys of a flag.
T qgsFlagKeysToValue(const QString &keys, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given keys of a flag.
#define Q_NOWARN_DEPRECATED_PUSH
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
T qgsgeometry_cast(QgsAbstractGeometry *geom)
QVector< QgsPolylineXY > QgsPolygonXY
Polygon: first item of the list is outer ring, inner rings (if any) start from second item.
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)
QList< QgsSymbolLayer * > QgsSymbolLayerList
QList< QPolygonF > offsetLine(QPolygonF polyline, double dist, Qgis::GeometryType geometryType)
calculate geometry shifted by a specified distance
QPolygonF lineStringToQPolygonF(const QgsLineString *line)
QPolygonF curveToPolygonF(const QgsCurve *curve)
void changeSymbolLayerIds(QgsSymbolLayer *sl, Functor &&generateId)
QMap< QString, QgsSymbol * > QgsSymbolMap
QMap< QString, QString > QgsStringMap
Contains information relating to a node (i.e.
QString identifier
A string identifying the node.
QgsStyleEntityVisitorInterface::NodeType type
Node type.
Contains information relating to the style entity currently being visited.
const QgsStyleEntityInterface * entity
Reference to style entity being visited.
QString identifier
A string identifying the style entity.