53#include <QDomDocument>
61#include <QRegularExpression>
68using namespace Qt::StringLiterals;
70#define POINTS_TO_MM 2.83464567
74 return u
"%1,%2,%3,%4"_s.arg( color.red() ).arg( color.green() ).arg( color.blue() ).arg( color.alpha() );
79 const QStringList lst = str.split(
',' );
80 if ( lst.count() < 3 )
84 int red, green, blue, alpha;
86 green = lst[1].toInt();
87 blue = lst[2].toInt();
89 if ( lst.count() > 3 )
91 alpha = lst[3].toInt();
93 return QColor( red, green, blue, alpha );
98 return QString::number( alpha / 255.0,
'g', 2 );
104 double alpha = str.toDouble( &ok );
105 if ( !ok || alpha > 1 )
107 else if ( alpha < 0 )
116 case QFont::StyleNormal:
118 case QFont::StyleItalic:
120 case QFont::StyleOblique:
129 if ( str ==
"normal"_L1 )
130 return QFont::StyleNormal;
131 if ( str ==
"italic"_L1 )
132 return QFont::StyleItalic;
133 if ( str ==
"oblique"_L1 )
134 return QFont::StyleOblique;
135 return QFont::StyleNormal;
151 return QString::number( weight * 800 / 99 + 100 );
157 const int weight = str.toInt( &ok );
159 return static_cast< int >( QFont::Normal );
167 return ( weight - 100 ) * 99 / 800;
182 case Qt::DashDotLine:
183 return u
"dash dot"_s;
184 case Qt::DashDotDotLine:
185 return u
"dash dot dot"_s;
193 if ( str ==
"no"_L1 )
195 if ( str ==
"solid"_L1 )
196 return Qt::SolidLine;
197 if ( str ==
"dash"_L1 )
199 if ( str ==
"dot"_L1 )
201 if ( str ==
"dash dot"_L1 )
202 return Qt::DashDotLine;
203 if ( str ==
"dash dot dot"_L1 )
204 return Qt::DashDotDotLine;
205 return Qt::SolidLine;
225 const QString cleaned = str.toLower().trimmed();
226 if ( cleaned ==
"bevel"_L1 )
227 return Qt::BevelJoin;
228 if ( cleaned ==
"miter"_L1 )
229 return Qt::MiterJoin;
230 if ( cleaned ==
"round"_L1 )
231 return Qt::RoundJoin;
232 return Qt::BevelJoin;
252 if ( str ==
"bevel"_L1 )
253 return Qt::BevelJoin;
254 if ( str ==
"mitre"_L1 )
255 return Qt::MiterJoin;
256 if ( str ==
"round"_L1 )
257 return Qt::RoundJoin;
258 return Qt::BevelJoin;
278 if ( str ==
"square"_L1 )
279 return Qt::SquareCap;
280 if ( str ==
"flat"_L1 )
282 if ( str ==
"round"_L1 )
284 return Qt::SquareCap;
304 if ( str ==
"square"_L1 )
305 return Qt::SquareCap;
306 if ( str ==
"butt"_L1 )
308 if ( str ==
"round"_L1 )
310 return Qt::SquareCap;
317 case Qt::SolidPattern:
320 return u
"horizontal"_s;
322 return u
"vertical"_s;
323 case Qt::CrossPattern:
325 case Qt::BDiagPattern:
326 return u
"b_diagonal"_s;
327 case Qt::FDiagPattern:
328 return u
"f_diagonal"_s;
329 case Qt::DiagCrossPattern:
330 return u
"diagonal_x"_s;
331 case Qt::Dense1Pattern:
333 case Qt::Dense2Pattern:
335 case Qt::Dense3Pattern:
337 case Qt::Dense4Pattern:
339 case Qt::Dense5Pattern:
341 case Qt::Dense6Pattern:
343 case Qt::Dense7Pattern:
354 if ( str ==
"solid"_L1 )
355 return Qt::SolidPattern;
356 if ( str ==
"horizontal"_L1 )
357 return Qt::HorPattern;
358 if ( str ==
"vertical"_L1 )
359 return Qt::VerPattern;
360 if ( str ==
"cross"_L1 )
361 return Qt::CrossPattern;
362 if ( str ==
"b_diagonal"_L1 )
363 return Qt::BDiagPattern;
364 if ( str ==
"f_diagonal"_L1 )
365 return Qt::FDiagPattern;
366 if ( str ==
"diagonal_x"_L1 )
367 return Qt::DiagCrossPattern;
368 if ( str ==
"dense1"_L1 )
369 return Qt::Dense1Pattern;
370 if ( str ==
"dense2"_L1 )
371 return Qt::Dense2Pattern;
372 if ( str ==
"dense3"_L1 )
373 return Qt::Dense3Pattern;
374 if ( str ==
"dense4"_L1 )
375 return Qt::Dense4Pattern;
376 if ( str ==
"dense5"_L1 )
377 return Qt::Dense5Pattern;
378 if ( str ==
"dense6"_L1 )
379 return Qt::Dense6Pattern;
380 if ( str ==
"dense7"_L1 )
381 return Qt::Dense7Pattern;
382 if ( str ==
"no"_L1 )
384 return Qt::SolidPattern;
391 case Qt::CrossPattern:
393 case Qt::DiagCrossPattern:
404 case Qt::BDiagPattern:
406 case Qt::FDiagPattern:
407 return u
"backslash"_s;
410 case Qt::Dense1Pattern:
411 case Qt::Dense2Pattern:
412 case Qt::Dense3Pattern:
413 case Qt::Dense4Pattern:
414 case Qt::Dense5Pattern:
415 case Qt::Dense6Pattern:
416 case Qt::Dense7Pattern:
426 if ( str ==
"horline"_L1 )
427 return Qt::HorPattern;
428 if ( str ==
"line"_L1 )
429 return Qt::VerPattern;
430 if ( str ==
"cross"_L1 )
431 return Qt::CrossPattern;
432 if ( str ==
"slash"_L1 )
433 return Qt::BDiagPattern;
434 if ( str ==
"backshash"_L1 )
435 return Qt::FDiagPattern;
437 return Qt::DiagCrossPattern;
439 if ( str.startsWith(
"brush://"_L1 ) )
455 case Qt::MPenCapStyle:
468 case Qt::SvgMiterJoin:
474 case Qt::MPenJoinStyle:
483 const QDomNodeList children = element.childNodes();
484 for (
int i = 0; i < children.size(); ++i )
486 const QDomElement childElement = children.at( i ).toElement();
487 if ( childElement.tagName() ==
"se:LineSymbolizer"_L1 || childElement.tagName() ==
"se:PointSymbolizer"_L1 || childElement.tagName() ==
"se:PolygonSymbolizer"_L1 )
495 const QString compareString =
string.trimmed();
499 if ( compareString.compare(
"feature"_L1, Qt::CaseInsensitive ) == 0 )
501 else if ( compareString.compare(
"viewport"_L1, Qt::CaseInsensitive ) == 0 )
511 switch ( coordinateReference )
516 return u
"viewport"_s;
532 auto evaluatedArrowHead = ARROW_HEAD_MAP.lookup( value.toString() );
533 if ( evaluatedArrowHead )
535 return *evaluatedArrowHead;
539 if ( value.toInt() == 1 )
541 else if ( value.toInt() == 2 )
543 else if ( value.toInt( &intOk ) == 0 && intOk )
562 auto evaluatedArrowType = ARROW_TYPE_MAP.lookup( value.toString() );
563 if ( evaluatedArrowType )
565 return *evaluatedArrowType;
569 if ( value.toInt() == 1 )
571 else if ( value.toInt() == 2 )
573 else if ( value.toInt( &intOk ) == 0 && intOk )
593 auto evaluatedMode = MARKER_CLIP_MODE_MAP.lookup(
string );
596 return *evaluatedMode;
613 return u
"centroid_within"_s;
615 return u
"completely_within"_s;
631 auto evaluatedMode = LINE_CLIP_MODE_MAP.lookup(
string );
634 return *evaluatedMode;
649 return u
"during_render"_s;
651 return u
"before_render"_s;
663 QStringList lst = str.split(
',' );
664 if ( lst.count() != 2 )
665 return QPointF( 0, 0 );
666 return QPointF( lst[0].toDouble(), lst[1].toDouble() );
677 if ( value.userType() == QMetaType::Type::QVariantList )
679 const QVariantList list = value.toList();
680 if ( list.size() != 2 )
684 bool convertOk =
false;
685 const double x = list.at( 0 ).toDouble( &convertOk );
688 const double y = list.at( 1 ).toDouble( &convertOk );
693 return QPointF( x, y );
701 const QStringList list = value.toString().trimmed().split(
',' );
702 if ( list.count() != 2 )
704 bool convertOk =
false;
705 const double x = list.at( 0 ).toDouble( &convertOk );
708 const double y = list.at( 1 ).toDouble( &convertOk );
713 return QPointF( x, y );
727 QStringList lst =
string.split(
',' );
728 if ( lst.count() != 2 )
729 return QSizeF( 0, 0 );
730 return QSizeF( lst[0].toDouble(), lst[1].toDouble() );
741 if ( value.userType() == QMetaType::Type::QVariantList )
743 const QVariantList list = value.toList();
744 if ( list.size() != 2 )
748 bool convertOk =
false;
749 const double x = list.at( 0 ).toDouble( &convertOk );
752 const double y = list.at( 1 ).toDouble( &convertOk );
757 return QSizeF( x, y );
765 const QStringList list = value.toString().trimmed().split(
',' );
766 if ( list.count() != 2 )
768 bool convertOk =
false;
769 const double x = list.at( 0 ).toDouble( &convertOk );
772 const double y = list.at( 1 ).toDouble( &convertOk );
777 return QSizeF( x, y );
797 if ( str.startsWith(
"3x:"_L1 ) )
800 const QString chopped = str.mid( 3 );
801 lst = chopped.split(
',' );
805 lst = str.split(
',' );
807 if ( lst.count() < 2 )
810 double minScale = lst[0].toDouble();
812 minScale = minScale != 0 ? 1.0 / minScale : 0;
813 double maxScale = lst[1].toDouble();
815 maxScale = maxScale != 0 ? 1.0 / maxScale : 0;
817 if ( lst.count() < 6 )
837 *scaleFactor = 0.001;
838 return u
"http://www.opengeospatial.org/se/units/metre"_s;
843 return u
"http://www.opengeospatial.org/se/units/metre"_s;
850 *scaleFactor = 1 / 0.28;
859 if ( str ==
"http://www.opengeospatial.org/se/units/metre"_L1 )
865 else if ( str ==
"http://www.opengeospatial.org/se/units/foot"_L1 )
868 *scaleFactor = 0.3048;
883 QString vectorString;
884 QVector<qreal>::const_iterator it = v.constBegin();
885 for ( ; it != v.constEnd(); ++it )
887 if ( it != v.constBegin() )
889 vectorString.append(
';' );
891 vectorString.append( QString::number( *it ) );
898 QVector<qreal> resultVector;
900 const QStringList realList = s.split(
';' );
901 QStringList::const_iterator it = realList.constBegin();
902 for ( ; it != realList.constEnd(); ++it )
904 resultVector.append( it->toDouble() );
912 QString vectorString;
913 QVector<qreal>::const_iterator it = v.constBegin();
914 for ( ; it != v.constEnd(); ++it )
916 if ( it != v.constBegin() )
918 vectorString.append(
' ' );
920 vectorString.append( QString::number( *it ) );
927 QVector<qreal> resultVector;
929 const QStringList realList = s.split(
' ' );
930 QStringList::const_iterator it = realList.constBegin();
931 for ( ; it != realList.constEnd(); ++it )
933 resultVector.append( it->toDouble() );
941 QString encodedValue;
943 switch ( scaleMethod )
946 encodedValue = u
"diameter"_s;
949 encodedValue = u
"area"_s;
959 if ( str ==
"diameter"_L1 )
973 if ( s.compare(
"Lighten"_L1, Qt::CaseInsensitive ) == 0 )
974 return QPainter::CompositionMode_Lighten;
975 if ( s.compare(
"Screen"_L1, Qt::CaseInsensitive ) == 0 )
976 return QPainter::CompositionMode_Screen;
977 if ( s.compare(
"Dodge"_L1, Qt::CaseInsensitive ) == 0 )
978 return QPainter::CompositionMode_ColorDodge;
979 if ( s.compare(
"Addition"_L1, Qt::CaseInsensitive ) == 0 )
980 return QPainter::CompositionMode_Plus;
981 if ( s.compare(
"Darken"_L1, Qt::CaseInsensitive ) == 0 )
982 return QPainter::CompositionMode_Darken;
983 if ( s.compare(
"Multiply"_L1, Qt::CaseInsensitive ) == 0 )
984 return QPainter::CompositionMode_Multiply;
985 if ( s.compare(
"Burn"_L1, Qt::CaseInsensitive ) == 0 )
986 return QPainter::CompositionMode_ColorBurn;
987 if ( s.compare(
"Overlay"_L1, Qt::CaseInsensitive ) == 0 )
988 return QPainter::CompositionMode_Overlay;
989 if ( s.compare(
"SoftLight"_L1, Qt::CaseInsensitive ) == 0 )
990 return QPainter::CompositionMode_SoftLight;
991 if ( s.compare(
"HardLight"_L1, Qt::CaseInsensitive ) == 0 )
992 return QPainter::CompositionMode_HardLight;
993 if ( s.compare(
"Difference"_L1, Qt::CaseInsensitive ) == 0 )
994 return QPainter::CompositionMode_Difference;
995 if ( s.compare(
"Subtract"_L1, Qt::CaseInsensitive ) == 0 )
996 return QPainter::CompositionMode_Exclusion;
997 return QPainter::CompositionMode_SourceOver;
1002 return QIcon(
symbolPreviewPixmap( symbol, size, padding,
nullptr,
false,
nullptr, shape, screen ) );
1012 QPixmap pixmap( size * devicePixelRatio );
1013 pixmap.setDevicePixelRatio( devicePixelRatio );
1015 pixmap.fill( Qt::transparent );
1017 painter.begin( &pixmap );
1018 if ( customContext )
1022 painter.setRenderHint( QPainter::Antialiasing );
1023 painter.setRenderHint( QPainter::SmoothPixmapTransform );
1026 if ( customContext )
1033 size.setWidth( size.rwidth() - ( padding * 2 ) );
1034 size.setHeight( size.rheight() - ( padding * 2 ) );
1035 painter.translate( padding, padding );
1043 std::unique_ptr<QgsSymbol> symbol_noDD( symbol->
clone() );
1045 for (
const auto &layer : layers )
1047 for (
int i = 0; i < layer->dataDefinedProperties().count(); ++i )
1049 QgsProperty &prop = layer->dataDefinedProperties().property( i );
1055 symbol_noDD->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape, screen );
1059 std::unique_ptr<QgsSymbol> symbolClone( symbol->
clone() );
1060 symbolClone->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape, screen );
1069 double maxBleed = 0;
1074 maxBleed = layerMaxBleed > maxBleed ? layerMaxBleed : maxBleed;
1084 painter.begin( &picture );
1085 painter.setRenderHint( QPainter::Antialiasing );
1095 switch ( parentSymbolType )
1110 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
1111 layerClone->drawPreviewIcon( symbolContext, size );
1121 QPixmap pixmap( size * devicePixelRatio );
1122 pixmap.setDevicePixelRatio( devicePixelRatio );
1123 pixmap.fill( Qt::transparent );
1125 painter.begin( &pixmap );
1126 painter.setRenderHint( QPainter::Antialiasing );
1144 switch ( parentSymbolType )
1159 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
1160 layerClone->drawPreviewIcon( symbolContext, size );
1162 return QIcon( pixmap );
1172 QPixmap pixmap( size );
1173 pixmap.fill( Qt::transparent );
1176 painter.begin( &pixmap );
1179 if ( drawTransparentBackground )
1180 drawStippledBackground( &painter, QRect( padding, padding, size.width() - padding * 2, size.height() - padding * 2 ) );
1184 switch ( direction )
1186 case Qt::Horizontal:
1188 for (
int i = 0; i < size.width(); i++ )
1190 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.width() ) );
1191 painter.setPen( pen );
1192 const int x = flipDirection ? size.width() - i - 1 : i;
1193 painter.drawLine( QLineF( x, 0 + padding, x, size.height() - 1 - padding ) );
1200 for (
int i = 0; i < size.height(); i++ )
1202 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.height() ) );
1203 painter.setPen( pen );
1204 const int y = flipDirection ? size.height() - i - 1 : i;
1205 painter.drawLine( QLineF( 0 + padding, y, size.width() - 1 - padding, y ) );
1218 uchar pixDataRGB[] = { 255, 255, 255, 255, 127, 127, 127, 255, 127, 127, 127, 255, 255, 255, 255, 255 };
1219 const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
1221 const int width = ( rect.width() < rect.height() ) ? rect.width() / 2.5 : rect.height() / 2.5;
1222 const QPixmap pix = QPixmap::fromImage( img.scaled( width, width ) );
1225 brush.setTexture( pix );
1226 painter->fillRect( rect, brush );
1231 const qreal s = ( markerSize - 1 ) / 2.0;
1236 p.setPen( QColor( 50, 100, 120, 200 ) );
1237 p.setBrush( QColor( 200, 200, 210, 120 ) );
1238 p.drawEllipse( x - s, y - s, s * 2, s * 2 );
1241 p.setPen( QColor( 255, 0, 0 ) );
1242 p.drawLine( x - s, y + s, x + s, y - s );
1243 p.drawLine( x - s, y - s, x + s, y + s );
1255static QPolygonF makeOffsetGeometry(
const QgsPolylineXY &polyline )
1257 int i, pointCount = polyline.count();
1259 QPolygonF resultLine;
1260 resultLine.resize( pointCount );
1264 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1265 resultLine[i] = QPointF( tempPtr->
x(), tempPtr->
y() );
1269static QList<QPolygonF> makeOffsetGeometry(
const QgsPolygonXY &polygon )
1271 QList<QPolygonF> resultGeom;
1272 resultGeom.reserve( polygon.size() );
1273 for (
int ring = 0; ring < polygon.size(); ++ring )
1274 resultGeom.append( makeOffsetGeometry( polygon[ring] ) );
1280 QList<QPolygonF> resultLine;
1282 if ( polyline.count() < 2 )
1284 resultLine.append( polyline );
1288 unsigned int i, pointCount = polyline.count();
1291 QPointF *tempPtr = polyline.data();
1292 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1293 tempPolyline[i] =
QgsPointXY( tempPtr->rx(), tempPtr->ry() );
1296 if ( !tempGeometry.
isNull() )
1298 const int quadSegments = 0;
1299 const double miterLimit = 2.0;
1306 if ( !offsetGeom.
isNull() )
1308 tempGeometry = offsetGeom;
1313 resultLine.append( makeOffsetGeometry( line ) );
1318 resultLine.append( makeOffsetGeometry( tempGeometry.
asPolygon() ) );
1324 resultLine.reserve( tempMPolyline.count() );
1325 for (
int part = 0; part < tempMPolyline.count(); ++part )
1327 resultLine.append( makeOffsetGeometry( tempMPolyline[part] ) );
1334 resultLine.reserve( tempMPolygon.count() );
1335 for (
int part = 0; part < tempMPolygon.count(); ++part )
1337 resultLine.append( makeOffsetGeometry( tempMPolygon[part] ) );
1345 resultLine.append( polyline );
1354 if ( element.isNull() )
1358 QDomNode layerNode = element.firstChild();
1360 while ( !layerNode.isNull() )
1362 QDomElement e = layerNode.toElement();
1363 if ( !e.isNull() && e.tagName() !=
"data_defined_properties"_L1 && e.tagName() !=
"buffer"_L1 )
1365 if ( e.tagName() !=
"layer"_L1 )
1371 std::unique_ptr< QgsSymbolLayer > layer =
loadSymbolLayer( e, context );
1375 const QDomElement s = e.firstChildElement( u
"symbol"_s );
1378 std::unique_ptr< QgsSymbol > subSymbol(
loadSymbol( s, context ) );
1385 layers.append( layer.release() );
1387 for (
int i = 0; i < subSymbol->symbolLayerCount(); ++i )
1389 layers.append( subSymbol->symbolLayer( i )->clone() );
1394 const bool res = layer->setSubSymbol( subSymbol.release() );
1397 QgsDebugError( u
"symbol layer refused subsymbol: "_s + s.attribute(
"name" ) );
1399 layers.append( layer.release() );
1404 layers.append( layer.release() );
1409 layerNode = layerNode.nextSibling();
1412 if ( layers.isEmpty() )
1418 const QString symbolType = element.attribute( u
"type"_s );
1420 std::unique_ptr< QgsSymbol > symbol;
1421 if ( symbolType ==
"line"_L1 )
1422 symbol = std::make_unique< QgsLineSymbol >( layers );
1423 else if ( symbolType ==
"fill"_L1 )
1424 symbol = std::make_unique< QgsFillSymbol >( layers );
1425 else if ( symbolType ==
"marker"_L1 )
1426 symbol = std::make_unique< QgsMarkerSymbol >( layers );
1433 if ( element.hasAttribute( u
"outputUnit"_s ) )
1437 if ( element.hasAttribute( ( u
"mapUnitScale"_s ) ) )
1440 const double oldMin = element.attribute( u
"mapUnitMinScale"_s, u
"0.0"_s ).toDouble();
1441 mapUnitScale.
minScale = oldMin != 0 ? 1.0 / oldMin : 0;
1442 const double oldMax = element.attribute( u
"mapUnitMaxScale"_s, u
"0.0"_s ).toDouble();
1443 mapUnitScale.
maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
1444 symbol->setMapUnitScale( mapUnitScale );
1446 symbol->setOpacity( element.attribute( u
"alpha"_s, u
"1.0"_s ).toDouble() );
1447 symbol->setExtentBuffer( element.attribute( u
"extent_buffer"_s, u
"0.0"_s ).toDouble() );
1449 symbol->setClipFeaturesToExtent( element.attribute( u
"clip_to_extent"_s, u
"1"_s ).toInt() );
1450 symbol->setForceRHR( element.attribute( u
"force_rhr"_s, u
"0"_s ).toInt() );
1452 if ( element.attribute( u
"renderer_should_use_levels"_s, u
"0"_s ).toInt() )
1454 symbol->setFlags( flags );
1456 symbol->animationSettings().setIsAnimated( element.attribute( u
"is_animated"_s, u
"0"_s ).toInt() );
1457 symbol->animationSettings().setFrameRate( element.attribute( u
"frame_rate"_s, u
"10"_s ).toDouble() );
1459 if ( !element.firstChildElement( u
"buffer"_s ).isNull() )
1461 auto bufferSettings = std::make_unique< QgsSymbolBufferSettings >();
1462 bufferSettings->readXml( element, context );
1463 symbol->setBufferSettings( bufferSettings.release() );
1467 symbol->setBufferSettings(
nullptr );
1470 const QDomElement ddProps = element.firstChildElement( u
"data_defined_properties"_s );
1471 if ( !ddProps.isNull() )
1481 const QString layerClass = element.attribute( u
"class"_s );
1482 const bool locked = element.attribute( u
"locked"_s ).toInt();
1483 const bool enabled = element.attribute( u
"enabled"_s, u
"1"_s ).toInt();
1484 const int pass = element.attribute( u
"pass"_s ).toInt();
1485 const QString
id = element.attribute( u
"id"_s );
1486 const QString selectiveMaskingSetId = element.attribute( u
"selectiveMaskingSet"_s );
1500 layer->setLocked( locked );
1501 layer->setRenderingPass( pass );
1502 layer->setEnabled( enabled );
1503 layer->setUserFlags( userFlags );
1504 layer->setSelectiveMaskingSourceSetId( selectiveMaskingSetId );
1507 if ( !
id.isEmpty() )
1511 const QDomElement effectElem = element.firstChildElement( u
"effect"_s );
1512 if ( !effectElem.isNull() )
1516 layer->setPaintEffect( effect.release() );
1520 const QDomElement ddProps = element.firstChildElement( u
"data_defined_properties"_s );
1521 if ( !ddProps.isNull() )
1528 const QSet< int > oldKeys = prevProperties.
propertyKeys();
1529 for (
int key : oldKeys )
1531 if ( !layer->dataDefinedProperties().propertyKeys().contains( key ) )
1563 QDomElement symEl = doc.createElement( u
"symbol"_s );
1564 symEl.setAttribute( u
"type"_s, _nameForSymbolType( symbol->
type() ) );
1565 symEl.setAttribute( u
"name"_s, name );
1566 symEl.setAttribute( u
"alpha"_s, QString::number( symbol->
opacity() ) );
1570 symEl.setAttribute( u
"extent_buffer"_s, QString::number( symbol->
extentBuffer() ) );
1573 symEl.setAttribute( u
"force_rhr"_s, symbol->
forceRHR() ? u
"1"_s : u
"0"_s );
1575 symEl.setAttribute( u
"renderer_should_use_levels"_s, u
"1"_s );
1581 bufferSettings->writeXml( symEl, context );
1585 QDomElement ddProps = doc.createElement( u
"data_defined_properties"_s );
1587 symEl.appendChild( ddProps );
1593 QDomElement layerEl = doc.createElement( u
"layer"_s );
1594 layerEl.setAttribute( u
"class"_s, layer->
layerType() );
1595 layerEl.setAttribute( u
"enabled"_s, layer->
enabled() );
1596 layerEl.setAttribute( u
"locked"_s, layer->
isLocked() );
1598 layerEl.setAttribute( u
"id"_s, layer->
id() );
1614 QDomElement ddProps = doc.createElement( u
"data_defined_properties"_s );
1616 layerEl.appendChild( ddProps );
1620 const QString subname = u
"@%1@%2"_s.arg( name ).arg( i );
1621 const QDomElement subEl =
saveSymbol( subname, subSymbol, doc, context );
1622 layerEl.appendChild( subEl );
1624 symEl.appendChild( layerEl );
1632 QDomDocument doc( u
"qgis-symbol-definition"_s );
1635 QTextStream stream( &props );
1636 symbolElem.save( stream, -1 );
1644 if ( element.isNull() )
1647 const QString symbolizerName = element.localName();
1649 if ( symbolizerName ==
"PointSymbolizer"_L1 )
1652 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1653 if ( graphicElem.isNull() )
1655 QgsDebugError( u
"Graphic element not found in PointSymbolizer"_s );
1666 layers.append( l.release() );
1676 layers.append( l.release() );
1686 layers.append( l.release() );
1698 if ( symbolizerName ==
"LineSymbolizer"_L1 )
1701 const QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
1702 if ( strokeElem.isNull() )
1704 QgsDebugError( u
"Stroke element not found in LineSymbolizer"_s );
1717 layers.append( l.release() );
1727 layers.append( l.release() );
1739 if ( symbolizerName ==
"PolygonSymbolizer"_L1 )
1742 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
1743 const QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
1744 if ( fillElem.isNull() && strokeElem.isNull() )
1746 QgsDebugError( u
"neither Fill nor Stroke element not found in PolygonSymbolizer"_s );
1760 layers.append( l.release() );
1764 if ( lastLayer->
layerType() ==
"SimpleFill"_L1 || lastLayer->
layerType() ==
"SVGFill"_L1 )
1772 layers.append( l.release() );
1782 layers.append( l.release() );
1805 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
1806 if ( fillElem.isNull() )
1812 std::unique_ptr< QgsSymbolLayer > l;
1830 const QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
1831 if ( strokeElem.isNull() )
1837 std::unique_ptr< QgsSymbolLayer > l;
1849 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1850 if ( graphicElem.isNull() )
1856 std::unique_ptr< QgsSymbolLayer > l;
1879 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1880 if ( graphicElem.isNull() )
1883 const QDomElement externalGraphicElem = graphicElem.firstChildElement( u
"ExternalGraphic"_s );
1884 if ( externalGraphicElem.isNull() )
1888 const QDomElement formatElem = externalGraphicElem.firstChildElement( u
"Format"_s );
1889 if ( formatElem.isNull() )
1892 const QString elementFormat = formatElem.firstChild().nodeValue();
1893 if ( !format.isEmpty() && elementFormat != format )
1895 QgsDebugMsgLevel(
"unsupported External Graphic format found: " + elementFormat, 4 );
1900 const QDomElement onlineResourceElem = externalGraphicElem.firstChildElement( u
"OnlineResource"_s );
1901 const QDomElement inlineContentElem = externalGraphicElem.firstChildElement( u
"InlineContent"_s );
1903 if ( !onlineResourceElem.isNull() )
1907 else if ( !inlineContentElem.isNull() )
1920 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1921 if ( graphicElem.isNull() )
1924 const QDomElement markElem = graphicElem.firstChildElement( u
"Mark"_s );
1925 if ( markElem.isNull() )
1928 const QDomElement wellKnownNameElem = markElem.firstChildElement( u
"WellKnownName"_s );
1929 return !wellKnownNameElem.isNull();
1935 const QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1936 if ( graphicElem.isNull() )
1939 const QDomElement markElem = graphicElem.firstChildElement( u
"Mark"_s );
1940 if ( markElem.isNull() )
1944 const QDomElement formatElem = markElem.firstChildElement( u
"Format"_s );
1945 if ( formatElem.isNull() )
1948 const QString format = formatElem.firstChild().nodeValue();
1949 if ( format !=
"ttf"_L1 )
1951 QgsDebugError(
"unsupported Graphic Mark format found: " + format );
1956 const QDomElement onlineResourceElem = markElem.firstChildElement( u
"OnlineResource"_s );
1957 const QDomElement inlineContentElem = markElem.firstChildElement( u
"InlineContent"_s );
1958 if ( !onlineResourceElem.isNull() )
1961 const QDomElement markIndexElem = markElem.firstChildElement( u
"MarkIndex"_s );
1962 if ( !markIndexElem.isNull() )
1965 else if ( !inlineContentElem.isNull() )
1986 QDomElement graphicElem = element.firstChildElement( u
"Graphic"_s );
1987 if ( graphicElem.isNull() )
1991 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
1993 if ( it.key() ==
"widthHeightFactor"_L1 )
2004 const QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
2005 if ( strokeElem.isNull() )
2008 QDomElement graphicStrokeElem = strokeElem.firstChildElement( u
"GraphicStroke"_s );
2009 if ( graphicStrokeElem.isNull() )
2017 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
2018 if ( fillElem.isNull() )
2021 const QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
2022 if ( graphicFillElem.isNull() )
2025 QDomElement graphicElem = graphicFillElem.firstChildElement( u
"Graphic"_s );
2026 if ( graphicElem.isNull() )
2032 QColor fillColor, strokeColor;
2033 double size, strokeWidth;
2034 Qt::PenStyle strokeStyle;
2035 if ( !
wellKnownMarkerFromSld( graphicElem, name, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
2038 if ( name !=
"horline"_L1 )
2046 const double angle = angleFunc.toDouble( &ok );
2052 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
2053 if ( fillElem.isNull() )
2056 const QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
2057 if ( graphicFillElem.isNull() )
2060 const QDomElement graphicElem = graphicFillElem.firstChildElement( u
"Graphic"_s );
2061 if ( graphicElem.isNull() )
2064 const QDomElement markElem = graphicElem.firstChildElement( u
"Mark"_s );
2065 if ( markElem.isNull() )
2073 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
2074 if ( fillElem.isNull() )
2077 QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
2078 if ( graphicFillElem.isNull() )
2086 const QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
2087 if ( fillElem.isNull() )
2090 QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
2091 if ( graphicFillElem.isNull() )
2111 QDomElement fillElem = element.firstChildElement( u
"Fill"_s );
2112 QDomElement strokeElem = element.firstChildElement( u
"Stroke"_s );
2116 bool validFill =
false, validStroke =
false;
2121 Qt::BrushStyle fillStyle;
2123 if (
fillFromSld( fillElem, fillStyle, fillColor ) )
2129 Qt::PenStyle strokeStyle;
2130 double strokeWidth = 1.0, dashOffset = 0.0;
2131 QVector<qreal> customDashPattern;
2133 if (
lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth,
nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2136 if ( validFill || validStroke )
2139 map[u
"name"_s] = u
"square"_s;
2142 map[u
"size"_s] = QString::number( 6 );
2143 map[u
"angle"_s] = QString::number( 0 );
2144 map[u
"offset"_s] =
encodePoint( QPointF( 0, 0 ) );
2151 bool validFill =
false, validStroke =
false;
2154 QString name, format;
2156 QColor fillColor, strokeColor;
2157 double strokeWidth = 1.0, size = 0.0, angle = 0.0;
2161 const QDomElement graphicFillElem = fillElem.firstChildElement( u
"GraphicFill"_s );
2162 if ( !graphicFillElem.isNull() )
2165 QDomElement graphicElem = graphicFillElem.firstChildElement( u
"Graphic"_s );
2166 if ( !graphicElem.isNull() )
2172 const QDomElement graphicChildElem = graphicElem.firstChildElement();
2173 while ( !graphicChildElem.isNull() )
2175 if ( graphicChildElem.localName() ==
"Mark"_L1 )
2178 const QDomElement wellKnownNameElem = graphicChildElem.firstChildElement( u
"WellKnownName"_s );
2179 if ( !wellKnownNameElem.isNull() )
2181 name = wellKnownNameElem.firstChild().nodeValue();
2187 if ( graphicChildElem.localName() ==
"ExternalGraphic"_L1 || graphicChildElem.localName() ==
"Mark"_L1 )
2190 const QDomElement formatElem = graphicChildElem.firstChildElement( u
"Format"_s );
2191 if ( formatElem.isNull() )
2194 format = formatElem.firstChild().nodeValue();
2198 if ( graphicChildElem.localName() ==
"ExternalGraphic"_L1 && format !=
"image/svg+xml"_L1 )
2203 if ( graphicChildElem.localName() ==
"Mark"_L1 && format !=
"ttf"_L1 )
2207 const QDomElement onlineResourceElem = graphicChildElem.firstChildElement( u
"OnlineResource"_s );
2208 const QDomElement inlineContentElem = graphicChildElem.firstChildElement( u
"InlineContent"_s );
2210 if ( !onlineResourceElem.isNull() )
2212 name = onlineResourceElem.attributeNS( u
"http://www.w3.org/1999/xlink"_s, u
"href"_s );
2214 if ( graphicChildElem.localName() ==
"Mark"_L1 && format ==
"ttf"_L1 )
2217 if ( name.startsWith(
"ttf://"_L1 ) )
2218 name = name.mid( 6 );
2221 const QDomElement markIndexElem = graphicChildElem.firstChildElement( u
"MarkIndex"_s );
2222 if ( markIndexElem.isNull() )
2226 const int v = markIndexElem.firstChild().nodeValue().toInt( &ok );
2237 else if ( !inlineContentElem.isNull() )
2247 if ( graphicChildElem.localName() ==
"Mark"_L1 )
2256 if ( found && graphicChildElem.localName() ==
"Mark"_L1 )
2263 Qt::BrushStyle markFillStyle;
2265 QDomElement markFillElem = graphicChildElem.firstChildElement( u
"Fill"_s );
2266 if (
fillFromSld( markFillElem, markFillStyle, fillColor ) )
2271 Qt::PenStyle strokeStyle;
2272 double strokeWidth = 1.0, dashOffset = 0.0;
2273 QVector<qreal> customDashPattern;
2275 QDomElement markStrokeElem = graphicChildElem.firstChildElement( u
"Stroke"_s );
2276 if (
lineFromSld( markStrokeElem, strokeStyle, strokeColor, strokeWidth,
nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2283 const QDomElement opacityElem = graphicElem.firstChildElement( u
"Opacity"_s );
2284 if ( !opacityElem.isNull() )
2285 fillColor.setAlpha(
decodeSldAlpha( opacityElem.firstChild().nodeValue() ) );
2287 const QDomElement sizeElem = graphicElem.firstChildElement( u
"Size"_s );
2288 if ( !sizeElem.isNull() )
2291 const double v = sizeElem.firstChild().nodeValue().toDouble( &ok );
2300 const double v = angleFunc.toDouble( &ok );
2310 if ( validFill || validStroke )
2312 if ( format ==
"image/svg+xml"_L1 )
2315 map[u
"name"_s] = name;
2316 map[u
"fill"_s] = fillColor.name();
2317 map[u
"outline"_s] = strokeColor.name();
2318 map[u
"outline-width"_s] = QString::number( strokeWidth );
2320 map[u
"size"_s] = QString::number( size );
2322 map[u
"angle"_s] = QString::number( angle );
2323 if ( !offset.isNull() )
2327 else if ( format ==
"ttf"_L1 )
2330 map[u
"font"_s] = name;
2331 map[u
"chr"_s] = markIndex;
2334 map[u
"size"_s] = QString::number( size );
2336 map[u
"angle"_s] = QString::number( angle );
2337 if ( !offset.isNull() )
2344 if ( layers.isEmpty() )
2347 layerList << layers;
2355 fillToSld( doc, element, context, brushStyle, color );
2360 QString patternName;
2361 switch ( brushStyle )
2366 case Qt::SolidPattern:
2367 if ( color.isValid() )
2370 if ( color.alpha() < 255 )
2375 case Qt::CrossPattern:
2376 case Qt::DiagCrossPattern:
2377 case Qt::HorPattern:
2378 case Qt::VerPattern:
2379 case Qt::BDiagPattern:
2380 case Qt::FDiagPattern:
2381 case Qt::Dense1Pattern:
2382 case Qt::Dense2Pattern:
2383 case Qt::Dense3Pattern:
2384 case Qt::Dense4Pattern:
2385 case Qt::Dense5Pattern:
2386 case Qt::Dense6Pattern:
2387 case Qt::Dense7Pattern:
2392 context.
pushWarning( QObject::tr(
"Brush style '%1' is not supported for SLD" ).arg( brushStyle ) );
2396 QDomElement graphicFillElem = doc.createElement( u
"se:GraphicFill"_s );
2397 element.appendChild( graphicFillElem );
2399 QDomElement graphicElem = doc.createElement( u
"se:Graphic"_s );
2400 graphicFillElem.appendChild( graphicElem );
2402 const QColor fillColor = patternName.startsWith(
"brush://"_L1 ) ? color : QColor();
2403 const QColor strokeColor = !patternName.startsWith(
"brush://"_L1 ) ? color : QColor();
2406 wellKnownMarkerToSld( doc, graphicElem, patternName, fillColor, strokeColor, Qt::SolidLine, context, -1, -1 );
2413 brushStyle = Qt::SolidPattern;
2414 color = QColor( 128, 128, 128 );
2416 if ( element.isNull() )
2418 brushStyle = Qt::NoBrush;
2423 const QDomElement graphicFillElem = element.firstChildElement( u
"GraphicFill"_s );
2425 if ( graphicFillElem.isNull() )
2428 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2430 QgsDebugMsgLevel( u
"found SvgParameter %1: %2"_s.arg( it.key(), it.value() ), 2 );
2432 if ( it.key() ==
"fill"_L1 )
2433 color = QColor( it.value() );
2434 else if ( it.key() ==
"fill-opacity"_L1 )
2440 QDomElement graphicElem = graphicFillElem.firstChildElement( u
"Graphic"_s );
2441 if ( graphicElem.isNull() )
2444 QString patternName = u
"square"_s;
2445 QColor fillColor, strokeColor;
2446 double strokeWidth, size;
2447 Qt::PenStyle strokeStyle;
2448 if ( !
wellKnownMarkerFromSld( graphicElem, patternName, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
2452 if ( brushStyle == Qt::NoBrush )
2455 const QColor
c = patternName.startsWith(
"brush://"_L1 ) ? fillColor : strokeColor;
2465 QDomElement &element,
2466 Qt::PenStyle penStyle,
2467 const QColor &color,
2470 const Qt::PenJoinStyle *penJoinStyle,
2471 const Qt::PenCapStyle *penCapStyle,
2472 const QVector<qreal> *customDashPattern,
2476 QVector<qreal> dashPattern;
2477 const QVector<qreal> *pattern = &dashPattern;
2479 if ( penStyle == Qt::CustomDashLine && !customDashPattern )
2481 context.
pushWarning( QObject::tr(
"WARNING: Custom dash pattern required but not provided. Using default dash pattern." ) );
2482 penStyle = Qt::DashLine;
2494 dashPattern.push_back( 4.0 );
2495 dashPattern.push_back( 2.0 );
2498 dashPattern.push_back( 1.0 );
2499 dashPattern.push_back( 2.0 );
2501 case Qt::DashDotLine:
2502 dashPattern.push_back( 4.0 );
2503 dashPattern.push_back( 2.0 );
2504 dashPattern.push_back( 1.0 );
2505 dashPattern.push_back( 2.0 );
2507 case Qt::DashDotDotLine:
2508 dashPattern.push_back( 4.0 );
2509 dashPattern.push_back( 2.0 );
2510 dashPattern.push_back( 1.0 );
2511 dashPattern.push_back( 2.0 );
2512 dashPattern.push_back( 1.0 );
2513 dashPattern.push_back( 2.0 );
2516 case Qt::CustomDashLine:
2517 Q_ASSERT( customDashPattern );
2518 pattern = customDashPattern;
2522 context.
pushWarning( QObject::tr(
"Pen style '%1' is not supported for SLD" ).arg( penStyle ) );
2526 if ( color.isValid() )
2529 if ( color.alpha() < 255 )
2536 else if ( width == 0 )
2546 if ( !pattern->isEmpty() )
2556 QDomElement &element, Qt::PenStyle &penStyle, QColor &color,
double &width, Qt::PenJoinStyle *penJoinStyle, Qt::PenCapStyle *penCapStyle, QVector<qreal> *customDashPattern,
double *dashOffset
2561 penStyle = Qt::SolidLine;
2562 color = QColor( 0, 0, 0 );
2565 *penJoinStyle = Qt::BevelJoin;
2567 *penCapStyle = Qt::SquareCap;
2568 if ( customDashPattern )
2569 customDashPattern->clear();
2573 if ( element.isNull() )
2575 penStyle = Qt::NoPen;
2581 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2583 QgsDebugMsgLevel( u
"found SvgParameter %1: %2"_s.arg( it.key(), it.value() ), 2 );
2585 if ( it.key() ==
"stroke"_L1 )
2587 color = QColor( it.value() );
2589 else if ( it.key() ==
"stroke-opacity"_L1 )
2593 else if ( it.key() ==
"stroke-width"_L1 )
2596 const double w = it.value().toDouble( &ok );
2600 else if ( it.key() ==
"stroke-linejoin"_L1 && penJoinStyle )
2604 else if ( it.key() ==
"stroke-linecap"_L1 && penCapStyle )
2608 else if ( it.key() ==
"stroke-dasharray"_L1 )
2611 if ( !dashPattern.isEmpty() )
2615 bool dashPatternFound =
false;
2617 if ( dashPattern.count() == 2 )
2619 if ( dashPattern.at( 0 ) == 4.0 && dashPattern.at( 1 ) == 2.0 )
2621 penStyle = Qt::DashLine;
2622 dashPatternFound =
true;
2624 else if ( dashPattern.at( 0 ) == 1.0 && dashPattern.at( 1 ) == 2.0 )
2626 penStyle = Qt::DotLine;
2627 dashPatternFound =
true;
2630 else if ( dashPattern.count() == 4 )
2632 if ( dashPattern.at( 0 ) == 4.0 && dashPattern.at( 1 ) == 2.0 && dashPattern.at( 2 ) == 1.0 && dashPattern.at( 3 ) == 2.0 )
2634 penStyle = Qt::DashDotLine;
2635 dashPatternFound =
true;
2638 else if ( dashPattern.count() == 6 )
2640 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 )
2642 penStyle = Qt::DashDotDotLine;
2643 dashPatternFound =
true;
2648 if ( !dashPatternFound )
2650 if ( customDashPattern )
2652 penStyle = Qt::CustomDashLine;
2653 *customDashPattern = dashPattern;
2657 QgsDebugMsgLevel( u
"custom dash pattern required but not provided. Using default dash pattern."_s, 2 );
2658 penStyle = Qt::DashLine;
2663 else if ( it.key() ==
"stroke-dashoffset"_L1 && dashOffset )
2666 const double d = it.value().toDouble( &ok );
2677 QDomElement externalGraphicElem = doc.createElement( u
"se:ExternalGraphic"_s );
2678 element.appendChild( externalGraphicElem );
2687 QDomElement sizeElem = doc.createElement( u
"se:Size"_s );
2689 element.appendChild( sizeElem );
2696 parametricSvgToSld( doc, graphicElem, path, fillColor, size, strokeColor, strokeWidth, context );
2700 QDomDocument &doc, QDomElement &graphicElem,
const QString &path,
const QColor &fillColor,
double size,
const QColor &strokeColor,
double strokeWidth,
QgsSldExportContext &context
2708 graphicElem.appendChild( doc.createComment( u
"Parametric SVG"_s ) );
2709 const QString parametricPath =
getSvgParametricPath( path, fillColor, strokeColor, strokeWidth );
2712 graphicElem.appendChild( doc.createComment( u
"Plain SVG fallback, no parameters"_s ) );
2715 graphicElem.appendChild( doc.createComment( u
"Well known marker fallback"_s ) );
2721 QDomElement sizeElem = doc.createElement( u
"se:Size"_s );
2723 graphicElem.appendChild( sizeElem );
2730 if ( fillColor.isValid() )
2732 url.addQueryItem( u
"fill"_s, fillColor.name() );
2733 url.addQueryItem( u
"fill-opacity"_s,
encodeSldAlpha( fillColor.alpha() ) );
2737 url.addQueryItem( u
"fill"_s, u
"#000000"_s );
2738 url.addQueryItem( u
"fill-opacity"_s, u
"1"_s );
2740 if ( strokeColor.isValid() )
2742 url.addQueryItem( u
"outline"_s, strokeColor.name() );
2743 url.addQueryItem( u
"outline-opacity"_s,
encodeSldAlpha( strokeColor.alpha() ) );
2747 url.addQueryItem( u
"outline"_s, u
"#000000"_s );
2748 url.addQueryItem( u
"outline-opacity"_s, u
"1"_s );
2750 url.addQueryItem( u
"outline-width"_s, QString::number( strokeWidth ) );
2751 const QString params = url.toString( QUrl::FullyEncoded );
2752 if ( params.isEmpty() )
2758 return basePath +
"?" + params;
2767 QDomElement externalGraphicElem = element.firstChildElement( u
"ExternalGraphic"_s );
2768 if ( externalGraphicElem.isNull() )
2773 const QDomElement sizeElem = element.firstChildElement( u
"Size"_s );
2774 if ( !sizeElem.isNull() )
2777 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2792 QDomDocument &doc, QDomElement &element,
const QString &path,
const QString &format,
QgsSldExportContext &context,
int *markIndex,
const QColor &color,
double size
2795 QDomElement markElem = doc.createElement( u
"se:Mark"_s );
2796 element.appendChild( markElem );
2802 QDomElement markIndexElem = doc.createElement( u
"se:MarkIndex"_s );
2803 markIndexElem.appendChild( doc.createTextNode( QString::number( *markIndex ) ) );
2804 markElem.appendChild( markIndexElem );
2808 QDomElement fillElem = doc.createElement( u
"se:Fill"_s );
2809 fillToSld( doc, fillElem, context, Qt::SolidPattern, color );
2810 markElem.appendChild( fillElem );
2815 QDomElement sizeElem = doc.createElement( u
"se:Size"_s );
2817 element.appendChild( sizeElem );
2829 QDomElement markElem = element.firstChildElement( u
"Mark"_s );
2830 if ( markElem.isNull() )
2835 const QDomElement markIndexElem = markElem.firstChildElement( u
"MarkIndex"_s );
2836 if ( !markIndexElem.isNull() )
2839 const int i = markIndexElem.firstChild().nodeValue().toInt( &ok );
2845 QDomElement fillElem = markElem.firstChildElement( u
"Fill"_s );
2846 Qt::BrushStyle b = Qt::SolidPattern;
2851 const QDomElement sizeElem = element.firstChildElement( u
"Size"_s );
2852 if ( !sizeElem.isNull() )
2855 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2864 QDomDocument &doc, QDomElement &element,
const QString &name,
const QColor &color,
const QColor &strokeColor, Qt::PenStyle strokeStyle,
double strokeWidth,
double size
2868 wellKnownMarkerToSld( doc, element, name, color, strokeColor, strokeStyle, context, strokeWidth, size );
2872 QDomDocument &doc, QDomElement &element,
const QString &name,
const QColor &color,
const QColor &strokeColor, Qt::PenStyle strokeStyle,
QgsSldExportContext &context,
double strokeWidth,
double size
2875 QDomElement markElem = doc.createElement( u
"se:Mark"_s );
2876 element.appendChild( markElem );
2878 QDomElement wellKnownNameElem = doc.createElement( u
"se:WellKnownName"_s );
2879 wellKnownNameElem.appendChild( doc.createTextNode( name ) );
2880 markElem.appendChild( wellKnownNameElem );
2883 if ( color.isValid() )
2885 QDomElement fillElem = doc.createElement( u
"se:Fill"_s );
2886 fillToSld( doc, fillElem, context, Qt::SolidPattern, color );
2887 markElem.appendChild( fillElem );
2891 if ( strokeColor.isValid() )
2893 QDomElement strokeElem = doc.createElement( u
"se:Stroke"_s );
2894 lineToSld( doc, strokeElem, strokeStyle, strokeColor, context, strokeWidth );
2895 markElem.appendChild( strokeElem );
2901 QDomElement sizeElem = doc.createElement( u
"se:Size"_s );
2903 element.appendChild( sizeElem );
2913 strokeColor = QColor( 0, 0, 0 );
2917 const QDomElement markElem = element.firstChildElement( u
"Mark"_s );
2918 if ( markElem.isNull() )
2921 const QDomElement wellKnownNameElem = markElem.firstChildElement( u
"WellKnownName"_s );
2922 if ( !wellKnownNameElem.isNull() )
2924 name = wellKnownNameElem.firstChild().nodeValue();
2929 QDomElement fillElem = markElem.firstChildElement( u
"Fill"_s );
2930 Qt::BrushStyle b = Qt::SolidPattern;
2935 QDomElement strokeElem = markElem.firstChildElement( u
"Stroke"_s );
2936 lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth );
2940 const QDomElement sizeElem = element.firstChildElement( u
"Size"_s );
2941 if ( !sizeElem.isNull() )
2944 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2960 if ( !rotationFunc.isEmpty() )
2962 QDomElement rotationElem = doc.createElement( u
"se:Rotation"_s );
2964 element.appendChild( rotationElem );
2970 QDomElement rotationElem = element.firstChildElement( u
"Rotation"_s );
2971 if ( !rotationElem.isNull() )
2986 if ( !alphaFunc.isEmpty() )
2988 QDomElement opacityElem = doc.createElement( u
"se:Opacity"_s );
2990 element.appendChild( opacityElem );
2996 QDomElement opacityElem = element.firstChildElement( u
"Opacity"_s );
2997 if ( !opacityElem.isNull() )
3006 if ( offset.isNull() )
3009 QDomElement displacementElem = doc.createElement( u
"se:Displacement"_s );
3010 element.appendChild( displacementElem );
3012 QDomElement dispXElem = doc.createElement( u
"se:DisplacementX"_s );
3013 dispXElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.x(), 2 ) ) );
3015 QDomElement dispYElem = doc.createElement( u
"se:DisplacementY"_s );
3016 dispYElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.y(), 2 ) ) );
3018 displacementElem.appendChild( dispXElem );
3019 displacementElem.appendChild( dispYElem );
3026 QDomElement anchorElem = doc.createElement( u
"se:AnchorPoint"_s );
3027 element.appendChild( anchorElem );
3029 QDomElement anchorXElem = doc.createElement( u
"se:AnchorPointX"_s );
3030 anchorXElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.x() ) ) );
3032 QDomElement anchorYElem = doc.createElement( u
"se:AnchorPointY"_s );
3033 anchorYElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.y() ) ) );
3035 anchorElem.appendChild( anchorXElem );
3036 anchorElem.appendChild( anchorYElem );
3041 offset = QPointF( 0, 0 );
3043 const QDomElement displacementElem = element.firstChildElement( u
"Displacement"_s );
3044 if ( displacementElem.isNull() )
3047 const QDomElement dispXElem = displacementElem.firstChildElement( u
"DisplacementX"_s );
3048 if ( !dispXElem.isNull() )
3051 const double offsetX = dispXElem.firstChild().nodeValue().toDouble( &ok );
3053 offset.setX( offsetX );
3056 const QDomElement dispYElem = displacementElem.firstChildElement( u
"DisplacementY"_s );
3057 if ( !dispYElem.isNull() )
3060 const double offsetY = dispYElem.firstChild().nodeValue().toDouble( &ok );
3062 offset.setY( offsetY );
3071 labelTextToSld( doc, element, label, font, context, color, size );
3076 QDomElement labelElem = doc.createElement( u
"se:Label"_s );
3077 labelElem.appendChild( doc.createTextNode( label ) );
3078 element.appendChild( labelElem );
3080 QDomElement fontElem = doc.createElement( u
"se:Font"_s );
3081 element.appendChild( fontElem );
3085 fontElem.appendChild( createSldParameterElement( doc,
"font-style",
encodeSldFontStyle( font.style() ) ) );
3086 fontElem.appendChild( createSldParameterElement( doc,
"font-weight",
encodeSldFontWeight( font.weight() ) ) );
3091 if ( color.isValid() )
3093 QDomElement fillElem = doc.createElement( u
"Fill"_s );
3094 fillToSld( doc, fillElem, context, Qt::SolidPattern, color );
3095 element.appendChild( fillElem );
3100 double width,
double mmScaleFactor,
double mapUnitScaleFactor,
const QColor &
c, Qt::PenJoinStyle joinStyle, Qt::PenCapStyle capStyle,
double offset,
const QVector<qreal> *dashPattern
3104 penStyle.append(
"PEN(" );
3105 penStyle.append(
"c:" );
3106 penStyle.append(
c.name() );
3107 penStyle.append(
",w:" );
3109 penStyle.append( QString::number( width * mmScaleFactor ) );
3110 penStyle.append(
"mm" );
3113 if ( dashPattern && !dashPattern->isEmpty() )
3115 penStyle.append(
",p:\"" );
3116 QVector<qreal>::const_iterator pIt = dashPattern->constBegin();
3117 for ( ; pIt != dashPattern->constEnd(); ++pIt )
3119 if ( pIt != dashPattern->constBegin() )
3121 penStyle.append(
' ' );
3123 penStyle.append( QString::number( *pIt * mapUnitScaleFactor ) );
3124 penStyle.append(
'g' );
3126 penStyle.append(
'\"' );
3130 penStyle.append(
",cap:" );
3134 penStyle.append(
'p' );
3137 penStyle.append(
'r' );
3141 penStyle.append(
'b' );
3145 penStyle.append(
",j:" );
3146 switch ( joinStyle )
3149 penStyle.append(
'b' );
3152 penStyle.append(
'r' );
3156 penStyle.append(
'm' );
3162 penStyle.append(
",dp:" );
3163 penStyle.append( QString::number( offset * mapUnitScaleFactor ) );
3164 penStyle.append(
'g' );
3167 penStyle.append(
')' );
3174 brushStyle.append(
"BRUSH(" );
3175 brushStyle.append(
"fc:" );
3176 brushStyle.append( fillColor.name() );
3177 brushStyle.append(
')' );
3189 if ( geomFunc.isEmpty() )
3192 QDomElement geometryElem = doc.createElement( u
"Geometry"_s );
3193 element.appendChild( geometryElem );
3223 QDomElement geometryElem = element.firstChildElement( u
"Geometry"_s );
3224 if ( geometryElem.isNull() )
3242 context.
pushError( QObject::tr(
"Parser error encountered when converting expression to SLD: %1 - Expression was: %2" ).arg( expr.
parserErrorString(), function ) );
3246 if ( !filterElem.isNull() )
3247 element.appendChild( filterElem );
3260 if ( function ==
"ELSE"_L1 )
3263 element.appendChild( filterElem );
3272 context.
pushError( QObject::tr(
"Parser error encountered when converting expression to SLD: %1 - Expression was: %2" ).arg( expr.
parserErrorString(), function ) );
3276 if ( !filterElem.isNull() )
3277 element.appendChild( filterElem );
3285 QDomElement elem = element;
3286 if ( element.tagName() !=
"Filter"_L1 )
3288 const QDomNodeList filterNodes = element.elementsByTagName( u
"Filter"_s );
3289 if ( !filterNodes.isEmpty() )
3291 elem = filterNodes.at( 0 ).toElement();
3295 if ( elem.isNull() )
3323 QDomElement onlineResourceElem = doc.createElement( u
"se:OnlineResource"_s );
3324 onlineResourceElem.setAttribute( u
"xlink:type"_s, u
"simple"_s );
3325 onlineResourceElem.setAttribute( u
"xlink:href"_s, url );
3326 element.appendChild( onlineResourceElem );
3328 QDomElement formatElem = doc.createElement( u
"se:Format"_s );
3329 formatElem.appendChild( doc.createTextNode( format ) );
3330 element.appendChild( formatElem );
3337 const QDomElement onlineResourceElem = element.firstChildElement( u
"OnlineResource"_s );
3338 if ( onlineResourceElem.isNull() )
3341 path = QUrl::fromPercentEncoding( onlineResourceElem.attributeNS( u
"http://www.w3.org/1999/xlink"_s, u
"href"_s ).toUtf8() );
3343 const QDomElement formatElem = element.firstChildElement( u
"Format"_s );
3344 if ( formatElem.isNull() )
3347 format = formatElem.firstChild().nodeValue();
3354 QDomElement nodeElem = doc.createElement( u
"se:SvgParameter"_s );
3355 nodeElem.setAttribute( u
"name"_s, name );
3356 nodeElem.appendChild( doc.createTextNode( value ) );
3365 QDomElement paramElem = element.firstChildElement();
3366 while ( !paramElem.isNull() )
3368 if ( paramElem.localName() ==
"SvgParameter"_L1 || paramElem.localName() ==
"CssParameter"_L1 )
3370 const QString name = paramElem.attribute( u
"name"_s );
3371 if ( paramElem.firstChild().nodeType() == QDomNode::TextNode )
3373 value = paramElem.firstChild().nodeValue();
3377 if ( paramElem.firstChild().nodeType() == QDomNode::ElementNode && paramElem.firstChild().localName() ==
"Literal"_L1 )
3380 value = paramElem.firstChild().firstChild().nodeValue();
3384 QgsDebugError( u
"unexpected child of %1"_s.arg( paramElem.localName() ) );
3388 if ( !name.isEmpty() && !value.isEmpty() )
3389 params[name] = value;
3392 paramElem = paramElem.nextSiblingElement();
3400 QDomElement nodeElem = doc.createElement( u
"se:VendorOption"_s );
3401 nodeElem.setAttribute( u
"name"_s, name );
3402 nodeElem.appendChild( doc.createTextNode( value ) );
3410 QDomElement paramElem = element.firstChildElement( u
"VendorOption"_s );
3411 while ( !paramElem.isNull() )
3413 const QString name = paramElem.attribute( u
"name"_s );
3414 const QString value = paramElem.firstChild().nodeValue();
3416 if ( !name.isEmpty() && !value.isEmpty() )
3417 params[name] = value;
3419 paramElem = paramElem.nextSiblingElement( u
"VendorOption"_s );
3429 if ( newSymbols.userType() == QMetaType::Type::QVariantMap )
3431 return newSymbols.toMap();
3438 QDomElement e = element.firstChildElement();
3439 while ( !e.isNull() )
3441 if ( e.tagName() ==
"prop"_L1 )
3443 const QString propKey = e.attribute( u
"k"_s );
3444 const QString propValue = e.attribute( u
"v"_s );
3445 props[propKey] = propValue;
3447 e = e.nextSiblingElement();
3464 QDomElement e = element.firstChildElement();
3466 while ( !e.isNull() )
3468 if ( e.tagName() ==
"symbol"_L1 )
3472 symbols.insert( e.attribute( u
"name"_s ), symbol.release() );
3478 e = e.nextSiblingElement();
3485 QStringList subsymbols;
3487 for ( QMap<QString, QgsSymbol *>::iterator it = symbols.begin(); it != symbols.end(); ++it )
3489 if ( it.key()[0] !=
'@' )
3493 subsymbols.append( it.key() );
3495 QStringList parts = it.key().split(
'@' );
3496 if ( parts.count() < 3 )
3498 QgsDebugError(
"found subsymbol with invalid name: " + it.key() );
3502 const QString symname = parts[1];
3503 const int symlayer = parts[2].toInt();
3505 if ( !symbols.contains( symname ) )
3507 QgsDebugError(
"subsymbol references invalid symbol: " + symname );
3515 QgsDebugError(
"subsymbol references invalid symbol layer: " + QString::number( symlayer ) );
3524 QgsDebugError(
"symbol layer refused subsymbol: " + it.key() );
3529 for (
int i = 0; i < subsymbols.count(); i++ )
3530 symbols.take( subsymbols[i] );
3537 QDomElement symbolsElem = doc.createElement( tagName );
3540 for ( QMap<QString, QgsSymbol *>::iterator its = symbols.begin(); its != symbols.end(); ++its )
3542 const QDomElement symEl =
saveSymbol( its.key(), its.value(), doc, context );
3543 symbolsElem.appendChild( symEl );
3551 qDeleteAll( symbols );
3560 std::unique_ptr< QMimeData > mimeData(
new QMimeData );
3562 QDomDocument symbolDoc;
3564 symbolDoc.appendChild( symbolElem );
3565 mimeData->setText( symbolDoc.toString() );
3568 mimeData->setColorData( symbol->
color() );
3578 const QString text = data->text();
3579 if ( !text.isEmpty() )
3584 if ( doc.setContent( text ) )
3586 elem = doc.documentElement();
3588 if ( elem.nodeName() !=
"symbol"_L1 )
3589 elem = elem.firstChildElement( u
"symbol"_s );
3600 const QString rampType = element.attribute( u
"type"_s );
3625 QDomElement rampEl = doc.createElement( u
"colorramp"_s );
3626 rampEl.setAttribute( u
"type"_s, ramp->
type() );
3627 rampEl.setAttribute( u
"name"_s, name );
3635 QVariantMap rampMap;
3637 rampMap.insert( u
"type"_s, ramp->
type() );
3638 rampMap.insert( u
"name"_s, name );
3640 const QVariantMap properties = ramp->
properties();
3642 QVariantMap propertyMap;
3643 for (
auto property = properties.constBegin(); property != properties.constEnd(); ++property )
3645 propertyMap.insert( property.key(), property.value() );
3648 rampMap.insert( u
"properties"_s, propertyMap );
3654 const QVariantMap rampMap = value.toMap();
3656 const QString rampType = rampMap.value( u
"type"_s ).toString();
3659 const QVariantMap propertyMap = rampMap.value( u
"properties"_s ).toMap();
3662 for (
auto property = propertyMap.constBegin(); property != propertyMap.constEnd(); ++property )
3664 props.insert( property.key(), property.value().toString() );
3686 if ( !color.isValid() )
3693 return color.name();
3698 QList<QColor> colors;
3701 const thread_local QRegularExpression sepCommaSpaceRegExp(
"(,|\\s)" );
3702 QStringList components = colorStr.simplified().split( sepCommaSpaceRegExp );
3703 QStringList::iterator it = components.begin();
3704 for ( ; it != components.end(); ++it )
3706 const QColor result =
parseColor( *it,
true );
3707 if ( result.isValid() )
3712 if ( colors.length() > 0 )
3718 const thread_local QRegularExpression sepCommaRegExp(
"(,|\n)" );
3719 components = colorStr.split( sepCommaRegExp );
3720 it = components.begin();
3721 for ( ; it != components.end(); ++it )
3723 const QColor result =
parseColor( *it,
true );
3724 if ( result.isValid() )
3729 if ( colors.length() > 0 )
3735 components = colorStr.simplified().split( QString(
' ' ) );
3736 it = components.begin();
3737 for ( ; it != components.end(); ++it )
3739 const QColor result =
parseColor( *it,
true );
3740 if ( result.isValid() )
3745 if ( colors.length() > 0 )
3751 components = colorStr.split(
'\n' );
3752 it = components.begin();
3753 for ( ; it != components.end(); ++it )
3755 const QColor result =
parseColor( *it,
true );
3756 if ( result.isValid() )
3769 auto mimeData = std::make_unique<QMimeData>();
3770 mimeData->setColorData( QVariant( color ) );
3771 mimeData->setText( color.name() );
3781 if ( mimeData->hasColor() )
3783 QColor mimeColor = mimeData->colorData().value<QColor>();
3784 if ( mimeColor.isValid() )
3792 if ( mimeData->hasText() )
3796 if ( textColor.isValid() )
3814 if ( data->hasFormat( u
"text/xml"_s ) )
3817 const QByteArray encodedData = data->data( u
"text/xml"_s );
3818 QDomDocument xmlDoc;
3819 xmlDoc.setContent( encodedData );
3821 const QDomElement dragDataElem = xmlDoc.documentElement();
3822 if ( dragDataElem.tagName() ==
"ColorSchemeModelDragData"_L1 )
3824 const QDomNodeList nodeList = dragDataElem.childNodes();
3825 const int nChildNodes = nodeList.size();
3826 QDomElement currentElem;
3828 for (
int i = 0; i < nChildNodes; ++i )
3830 currentElem = nodeList.at( i ).toElement();
3831 if ( currentElem.isNull() )
3836 QPair< QColor, QString> namedColor;
3838 namedColor.second = currentElem.attribute( u
"label"_s, QString() );
3840 mimeColors << namedColor;
3845 if ( mimeColors.length() == 0 && data->hasFormat( u
"application/x-colorobject-list"_s ) )
3848 const QByteArray encodedData = data->data( u
"application/x-colorobject-list"_s );
3849 QDomDocument xmlDoc;
3850 xmlDoc.setContent( encodedData );
3852 const QDomNodeList colorsNodes = xmlDoc.elementsByTagName( u
"colors"_s );
3853 if ( colorsNodes.length() > 0 )
3855 const QDomElement colorsElem = colorsNodes.at( 0 ).toElement();
3856 const QDomNodeList colorNodeList = colorsElem.childNodes();
3857 const int nChildNodes = colorNodeList.size();
3858 QDomElement currentElem;
3860 for (
int i = 0; i < nChildNodes; ++i )
3863 currentElem = colorNodeList.at( i ).toElement();
3864 if ( currentElem.isNull() )
3869 const QDomNodeList colorNodes = currentElem.elementsByTagName( u
"color"_s );
3870 const QDomNodeList nameNodes = currentElem.elementsByTagName( u
"name"_s );
3872 if ( colorNodes.length() > 0 )
3874 const QDomElement colorElem = colorNodes.at( 0 ).toElement();
3876 const QStringList colorParts = colorElem.text().simplified().split(
' ' );
3877 if ( colorParts.length() < 3 )
3882 const int red = colorParts.at( 0 ).toDouble() * 255;
3883 const int green = colorParts.at( 1 ).toDouble() * 255;
3884 const int blue = colorParts.at( 2 ).toDouble() * 255;
3885 QPair< QColor, QString> namedColor;
3886 namedColor.first = QColor( red, green, blue );
3887 if ( nameNodes.length() > 0 )
3889 const QDomElement nameElem = nameNodes.at( 0 ).toElement();
3890 namedColor.second = nameElem.text();
3892 mimeColors << namedColor;
3898 if ( mimeColors.length() == 0 && data->hasText() )
3902 QList< QColor >::iterator it = parsedColors.begin();
3903 for ( ; it != parsedColors.end(); ++it )
3905 mimeColors << qMakePair( *it, QString() );
3909 if ( mimeColors.length() == 0 && data->hasColor() )
3912 const QColor mimeColor = data->colorData().value<QColor>();
3913 if ( mimeColor.isValid() )
3915 mimeColors << qMakePair( mimeColor, QString() );
3925 auto mimeData = std::make_unique<QMimeData>();
3926 QDomDocument xmlDoc;
3927 QDomElement xmlRootElement = xmlDoc.createElement( u
"ColorSchemeModelDragData"_s );
3928 xmlDoc.appendChild( xmlRootElement );
3930 QgsNamedColorList::const_iterator colorIt = colorList.constBegin();
3931 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3933 QDomElement namedColor = xmlDoc.createElement( u
"NamedColor"_s );
3935 namedColor.setAttribute( u
"label"_s, ( *colorIt ).second );
3936 xmlRootElement.appendChild( namedColor );
3938 mimeData->setData( u
"text/xml"_s, xmlDoc.toByteArray() );
3946 colorIt = colorList.constBegin();
3947 QStringList colorListString;
3948 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3950 colorListString << ( *colorIt ).first.name();
3952 mimeData->setText( colorListString.join( QLatin1Char(
'\n' ) ) );
3955 if ( colorList.length() > 0 )
3957 mimeData->setColorData( QVariant( colorList.at( 0 ).first ) );
3965 if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3970 QTextStream stream( &file );
3972 stream <<
"GIMP Palette" << Qt::endl;
3973 if ( paletteName.isEmpty() )
3975 stream <<
"Name: QGIS Palette" << Qt::endl;
3979 stream <<
"Name: " << paletteName << Qt::endl;
3981 stream <<
"Columns: 4" << Qt::endl;
3982 stream <<
'#' << Qt::endl;
3984 for ( QgsNamedColorList::ConstIterator colorIt = colors.constBegin(); colorIt != colors.constEnd(); ++colorIt )
3986 const QColor color = ( *colorIt ).first;
3987 if ( !color.isValid() )
3991 stream << u
"%1 %2 %3"_s.arg( color.red(), 3 ).arg( color.green(), 3 ).arg( color.blue(), 3 );
3992 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << Qt::endl;
4003 if ( !file.open( QIODevice::ReadOnly ) )
4006 return importedColors;
4009 QTextStream in( &file );
4011 QString line = in.readLine();
4012 if ( !line.startsWith(
"GIMP Palette"_L1 ) )
4015 return importedColors;
4019 while ( !in.atEnd() && !line.startsWith(
"Name:"_L1 ) && !line.startsWith(
'#' ) )
4021 line = in.readLine();
4023 if ( line.startsWith(
"Name:"_L1 ) )
4025 const thread_local QRegularExpression nameRx(
"Name:\\s*(\\S.*)$" );
4026 const QRegularExpressionMatch match = nameRx.match( line );
4027 if ( match.hasMatch() )
4029 name = match.captured( 1 );
4034 while ( !in.atEnd() && !line.startsWith(
'#' ) )
4036 line = in.readLine();
4041 return importedColors;
4045 const thread_local QRegularExpression rx(
"^\\s*(\\d+)\\s+(\\d+)\\s+(\\d+)(\\s.*)?$" );
4046 while ( !in.atEnd() )
4048 line = in.readLine();
4049 const QRegularExpressionMatch match = rx.match( line );
4050 if ( !match.hasMatch() )
4054 const int red = match.captured( 1 ).toInt();
4055 const int green = match.captured( 2 ).toInt();
4056 const int blue = match.captured( 3 ).toInt();
4057 const QColor color = QColor( red, green, blue );
4058 if ( !color.isValid() )
4065 if ( rx.captureCount() > 3 )
4067 label = match.captured( 4 ).simplified();
4074 importedColors << qMakePair( color, label );
4079 return importedColors;
4092 const thread_local QRegularExpression hexColorAlphaRx(
"^\\s*#?([0-9a-fA-F]{6})([0-9a-fA-F]{2})\\s*$" );
4093 QRegularExpressionMatch match = hexColorAlphaRx.match( colorStr );
4096 if ( !match.hasMatch() && QColor::isValidColor( colorStr ) )
4099 parsedColor.setNamedColor( colorStr );
4100 if ( parsedColor.isValid() )
4102 containsAlpha =
false;
4108 if ( match.hasMatch() )
4110 const QString hexColor = match.captured( 1 );
4111 parsedColor.setNamedColor( u
"#"_s + hexColor );
4113 const int alphaHex = match.captured( 2 ).toInt( &alphaOk, 16 );
4115 if ( parsedColor.isValid() && alphaOk )
4117 parsedColor.setAlpha( alphaHex );
4118 containsAlpha =
true;
4126 const thread_local QRegularExpression hexColorRx2(
"^\\s*(?:[0-9a-fA-F]{3}){1,2}\\s*$" );
4127 if ( colorStr.indexOf( hexColorRx2 ) != -1 )
4130 parsedColor.setNamedColor( u
"#"_s + colorStr );
4131 if ( parsedColor.isValid() )
4133 containsAlpha =
false;
4140 const thread_local QRegularExpression rgbFormatRx(
4141 "^\\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])(?:\\."
4142 "\\d*)?)\\s*\\)?\\s*;?\\s*$"
4144 match = rgbFormatRx.match( colorStr );
4145 if ( match.hasMatch() )
4150 const int r = match.captured( 1 ).toInt( &rOk );
4151 const int g = match.captured( 2 ).toInt( &gOk );
4152 const int b = match.captured( 3 ).toInt( &bOk );
4154 if ( !rOk || !gOk || !bOk )
4156 const float rFloat = match.captured( 1 ).toFloat();
4157 const float gFloat = match.captured( 2 ).toFloat();
4158 const float bFloat = match.captured( 3 ).toFloat();
4159 parsedColor.setRgbF( rFloat / 255.0, gFloat / 255.0, bFloat / 255.0 );
4163 parsedColor.setRgb( r, g, b );
4166 if ( parsedColor.isValid() )
4168 containsAlpha =
false;
4174 const thread_local QRegularExpression hslFormatRx(
"^\\s*hsl\\(?\\s*(\\d+(?:\\.\\d*)?)\\s*,\\s*(\\d+(?:\\.\\d*)?)\\s*%\\s*,\\s*(\\d+(?:\\.\\d*)?)\\s*%\\s*\\)?\\s*;?\\s*$" );
4175 match = hslFormatRx.match( colorStr );
4176 if ( match.hasMatch() )
4181 const int h = match.captured( 1 ).toInt( &hOk );
4182 const int s = match.captured( 2 ).toInt( &sOk );
4183 const int l = match.captured( 3 ).toInt( &lOk );
4185 if ( !hOk || !sOk || !lOk )
4187 const float hFloat = match.captured( 1 ).toFloat();
4188 const float sFloat = match.captured( 2 ).toFloat();
4189 const float lFloat = match.captured( 3 ).toFloat();
4190 parsedColor.setHslF( hFloat / 360.0, sFloat / 100.0, lFloat / 100.0 );
4194 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0 );
4196 if ( parsedColor.isValid() )
4198 containsAlpha =
false;
4204 const thread_local QRegularExpression rgbPercentFormatRx(
4205 "^\\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*$"
4207 match = rgbPercentFormatRx.match( colorStr );
4208 if ( match.hasMatch() )
4210 const double r = match.captured( 1 ).toDouble() / 100;
4211 const double g = match.captured( 2 ).toDouble() / 100;
4212 const double b = match.captured( 3 ).toDouble() / 100;
4213 parsedColor.setRgbF( r, g, b );
4214 if ( parsedColor.isValid() )
4216 containsAlpha =
false;
4222 const thread_local QRegularExpression rgbaFormatRx(
4223 "^\\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])(?:"
4224 "\\.\\d*)?)\\s*,\\s*(0|0?\\.\\d*|1(?:\\.0*)?)\\s*\\)?\\s*;?\\s*$"
4226 match = rgbaFormatRx.match( colorStr );
4227 if ( match.hasMatch() )
4232 const int r = match.captured( 1 ).toInt( &rOk );
4233 const int g = match.captured( 2 ).toInt( &gOk );
4234 const int b = match.captured( 3 ).toInt( &bOk );
4235 const double aDouble = match.captured( 4 ).toDouble();
4237 if ( !rOk || !gOk || !bOk )
4239 const float rFloat = match.captured( 1 ).toFloat();
4240 const float gFloat = match.captured( 2 ).toFloat();
4241 const float bFloat = match.captured( 3 ).toFloat();
4242 parsedColor.setRgbF( rFloat / 255.0, gFloat / 255.0, bFloat / 255.0, aDouble );
4246 const int a =
static_cast< int >( std::round( match.captured( 4 ).toDouble() * 255.0 ) );
4247 parsedColor.setRgb( r, g, b, a );
4249 if ( parsedColor.isValid() )
4251 containsAlpha =
true;
4257 const thread_local QRegularExpression rgbaPercentFormatRx(
4258 "^\\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*$"
4260 match = rgbaPercentFormatRx.match( colorStr );
4261 if ( match.hasMatch() )
4263 const double r = match.captured( 1 ).toDouble() / 100;
4264 const double g = match.captured( 2 ).toDouble() / 100;
4265 const double b = match.captured( 3 ).toDouble() / 100;
4266 const double a = match.captured( 4 ).toDouble();
4267 parsedColor.setRgbF( r, g, b, a );
4268 if ( parsedColor.isValid() )
4270 containsAlpha =
true;
4276 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*$" );
4277 match = hslaPercentFormatRx.match( colorStr );
4278 if ( match.hasMatch() )
4283 const int h = match.captured( 1 ).toInt( &hOk );
4284 const int s = match.captured( 2 ).toInt( &sOk );
4285 const int l = match.captured( 3 ).toInt( &lOk );
4286 const double aDouble = match.captured( 4 ).toDouble();
4288 if ( !hOk || !sOk || !lOk )
4290 const float hFloat = match.captured( 1 ).toFloat();
4291 const float sFloat = match.captured( 2 ).toFloat();
4292 const float lFloat = match.captured( 3 ).toFloat();
4293 parsedColor.setHslF( hFloat / 360.0, sFloat / 100.0, lFloat / 100.0, aDouble );
4297 const int a = std::round( aDouble * 255.0 );
4298 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0, a );
4301 if ( parsedColor.isValid() )
4303 containsAlpha =
true;
4320 const QImage::Format format = image->format();
4321 if ( format != QImage::Format_ARGB32_Premultiplied && format != QImage::Format_ARGB32 )
4328 for (
int heightIndex = 0; heightIndex < image->height(); ++heightIndex )
4330 QRgb *scanLine =
reinterpret_cast< QRgb *
>( image->scanLine( heightIndex ) );
4331 for (
int widthIndex = 0; widthIndex < image->width(); ++widthIndex )
4333 myRgb = scanLine[widthIndex];
4334 if ( format == QImage::Format_ARGB32_Premultiplied )
4335 scanLine[widthIndex] = qRgba( opacity * qRed( myRgb ), opacity * qGreen( myRgb ), opacity * qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4337 scanLine[widthIndex] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4345 const int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
4346 const int alpha = ( radius < 1 ) ? 16 : ( radius > 17 ) ? 1 : tab[radius - 1];
4348 if ( image.format() != QImage::Format_ARGB32_Premultiplied && image.format() != QImage::Format_RGB32 )
4350 image = image.convertToFormat( QImage::Format_ARGB32_Premultiplied );
4353 const int r1 = rect.top();
4354 const int r2 = rect.bottom();
4355 const int c1 = rect.left();
4356 const int c2 = rect.right();
4358 const int bpl = image.bytesPerLine();
4366 i1 = i2 = ( QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3 );
4368 for (
int col = c1; col <= c2; col++ )
4370 p = image.scanLine( r1 ) + col * 4;
4371 for (
int i = i1; i <= i2; i++ )
4372 rgba[i] = p[i] << 4;
4375 for (
int j = r1; j < r2; j++, p += bpl )
4376 for (
int i = i1; i <= i2; i++ )
4377 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4380 for (
int row = r1; row <= r2; row++ )
4382 p = image.scanLine( row ) + c1 * 4;
4383 for (
int i = i1; i <= i2; i++ )
4384 rgba[i] = p[i] << 4;
4387 for (
int j = c1; j < c2; j++, p += 4 )
4388 for (
int i = i1; i <= i2; i++ )
4389 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4392 for (
int col = c1; col <= c2; col++ )
4394 p = image.scanLine( r2 ) + col * 4;
4395 for (
int i = i1; i <= i2; i++ )
4396 rgba[i] = p[i] << 4;
4399 for (
int j = r1; j < r2; j++, p -= bpl )
4400 for (
int i = i1; i <= i2; i++ )
4401 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4404 for (
int row = r1; row <= r2; row++ )
4406 p = image.scanLine( row ) + c2 * 4;
4407 for (
int i = i1; i <= i2; i++ )
4408 rgba[i] = p[i] << 4;
4411 for (
int j = c1; j < c2; j++, p -= 4 )
4412 for (
int i = i1; i <= i2; i++ )
4413 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4419 if ( alpha != 255 && alpha > 0 )
4423 const double alphaFactor = alpha / 255.;
4424 int r = 0, g = 0, b = 0;
4425 rgb.getRgb( &r, &g, &b );
4430 rgb.setRgb( r, g, b, alpha );
4432 else if ( alpha == 0 )
4434 rgb.setRgb( 0, 0, 0, 0 );
4443 if ( !simpleFill || !simpleLine )
4467 if ( simpleLine->
offset() )
4485 if ( order == Qt::AscendingOrder )
4499 const double dx = directionPoint.x() - startPoint.x();
4500 const double dy = directionPoint.y() - startPoint.y();
4501 const double length = std::sqrt( dx * dx + dy * dy );
4502 const double scaleFactor = distance / length;
4503 return QPointF( startPoint.x() + dx * scaleFactor, startPoint.y() + dy * scaleFactor );
4513 for (
int i = 0; i < svgPaths.size(); i++ )
4515 const QDir dir( svgPaths[i] );
4516 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4517 for (
const QString &item : svgSubPaths )
4519 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4522 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4523 for (
const QString &item : svgFiles )
4526 list.append( dir.path() +
'/' + item );
4538 QStringList svgPaths;
4539 svgPaths.append( directory );
4541 for (
int i = 0; i < svgPaths.size(); i++ )
4543 const QDir dir( svgPaths[i] );
4544 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4545 for (
const QString &item : svgSubPaths )
4547 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4550 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4551 for (
const QString &item : svgFiles )
4553 list.append( dir.path() +
'/' + item );
4564 if ( n.startsWith(
"base64:"_L1 ) )
4568 if ( QFileInfo::exists( n ) )
4569 return QFileInfo( n ).canonicalFilePath();
4573 if ( name.contains(
"://"_L1 ) )
4575 const QUrl url( name );
4576 if ( url.isValid() && !url.scheme().isEmpty() )
4578 if ( url.scheme().compare(
"file"_L1, Qt::CaseInsensitive ) == 0 )
4581 name = url.toLocalFile();
4582 if ( QFile( name ).exists() )
4584 return QFileInfo( name ).canonicalFilePath();
4598 for (
int i = 0; i < svgPaths.size(); i++ )
4600 QString svgPath = svgPaths[i];
4601 if ( svgPath.endsWith( QChar(
'/' ) ) )
4612 const QString myLocalPath = svgPath + QDir::separator() + name;
4615 if ( QFile( myLocalPath ).exists() )
4618 return QFileInfo( myLocalPath ).canonicalFilePath();
4622 return pathResolver.
readPath( name );
4630 if ( p.startsWith(
"base64:"_L1 ) )
4633 if ( !QFileInfo::exists( p ) )
4636 QString path = QFileInfo( p ).canonicalFilePath();
4640 bool isInSvgPaths =
false;
4641 for (
int i = 0; i < svgPaths.size(); i++ )
4643 const QString dir = QFileInfo( svgPaths[i] ).canonicalFilePath();
4645 if ( !dir.isEmpty() && path.startsWith( dir ) )
4647 path = path.mid( dir.size() + 1 );
4648 isInSvgPaths =
true;
4661 const double *srcX = line->
xData();
4662 const double *srcY = line->
yData();
4664 QPolygonF thisRes( count );
4665 QPointF *dest = thisRes.data();
4666 for (
int i = 0; i < count; ++i )
4668 *dest++ = QPointF( *srcX++, *srcY++ );
4681 const std::unique_ptr< QgsLineString > straightened( curve->
curveToLine() );
4705 points << QPointF( ( *it ).x(), ( *it ).y() );
4709 points << QPointF( 0, 0 );
4711 return QList< QList<QPolygonF> >() << ( QList< QPolygonF >() << points );
4716 QList< QList<QPolygonF> > res;
4729 QList< QList<QPolygonF> > res;
4733 QList<QPolygonF> thisPart;
4752 return QList< QList<QPolygonF> >();
4755 return QList< QList<QPolygonF> >();
4762 double cx = 0, cy = 0;
4763 double area, sum = 0;
4764 for (
int i = points.count() - 1, j = 0; j < points.count(); i = j++ )
4766 const QPointF &p1 = points[i];
4767 const QPointF &p2 = points[j];
4768 area = p1.x() * p2.y() - p1.y() * p2.x();
4770 cx += ( p1.x() + p2.x() ) * area;
4771 cy += ( p1.y() + p2.y() ) * area;
4778 if ( points.count() >= 2 )
4779 return QPointF( ( points[0].x() + points[1].x() ) / 2, ( points[0].y() + points[1].y() ) / 2 );
4780 else if ( points.count() == 1 )
4788 return QPointF( cx, cy );
4795 if ( ( rings && rings->count() > 0 ) || !
pointInPolygon( points, centroid ) )
4797 unsigned int i, pointCount = points.count();
4799 for ( i = 0; i < pointCount; ++i )
4800 polyline[i] =
QgsPointXY( points[i].x(), points[i].y() );
4806 for (
auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
4808 pointCount = ( *ringIt ).count();
4810 for ( i = 0; i < pointCount; ++i )
4811 polyline[i] =
QgsPointXY( ( *ringIt )[i].x(), ( *ringIt )[i].y() );
4817 if ( !pointOnSurfaceGeom.
isNull() )
4820 centroid.
setX( point.
x() );
4821 centroid.setY( point.
y() );
4826 return QPointF( centroid.x(), centroid.y() );
4831 bool inside =
false;
4833 const double x = point.x();
4834 const double y = point.y();
4836 for (
int i = 0, j = points.count() - 1; i < points.count(); i++ )
4838 const QPointF &p1 = points[i];
4839 const QPointF &p2 = points[j];
4844 if ( ( p1.y() < y && p2.y() >= y ) || ( p2.y() < y && p1.y() >= y ) )
4846 if ( p1.x() + ( y - p1.y() ) / ( p2.y() - p1.y() ) * ( p2.x() - p1.x() ) <= x )
4857 if ( polyline.size() < 2 )
4860 double totalLength = 0;
4861 auto it = polyline.begin();
4863 for ( ; it != polyline.end(); ++it )
4865 const QPointF p2 = *it;
4866 const double segmentLength = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4867 totalLength += segmentLength;
4875 if ( polyline.size() < 2 )
4878 double totalLength = 0;
4879 auto it = polyline.begin();
4881 std::vector< double > segmentLengths( polyline.size() - 1 );
4882 auto segmentLengthIt = segmentLengths.begin();
4883 for ( ; it != polyline.end(); ++it )
4885 const QPointF p2 = *it;
4886 *segmentLengthIt = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4887 totalLength += *segmentLengthIt;
4893 if ( startOffset >= 0 && totalLength <= startOffset )
4895 if ( endOffset < 0 && totalLength <= -endOffset )
4898 const double startDistance = startOffset < 0 ? totalLength + startOffset : startOffset;
4899 const double endDistance = endOffset <= 0 ? totalLength + endOffset : endOffset;
4900 QPolygonF substringPoints;
4901 substringPoints.reserve( polyline.size() );
4903 it = polyline.begin();
4904 segmentLengthIt = segmentLengths.begin();
4907 bool foundStart =
false;
4908 if (
qgsDoubleNear( startDistance, 0.0 ) || startDistance < 0 )
4910 substringPoints << p1;
4914 double distanceTraversed = 0;
4915 for ( ; it != polyline.end(); ++it )
4917 const QPointF p2 = *it;
4918 if ( distanceTraversed < startDistance && distanceTraversed + *segmentLengthIt > startDistance )
4921 const double distanceToStart = startDistance - distanceTraversed;
4922 double startX, startY;
4924 substringPoints << QPointF( startX, startY );
4927 if ( foundStart && ( distanceTraversed + *segmentLengthIt > endDistance ) )
4930 const double distanceToEnd = endDistance - distanceTraversed;
4933 if ( substringPoints.last() != QPointF( endX, endY ) )
4934 substringPoints << QPointF( endX, endY );
4936 else if ( foundStart )
4938 if ( substringPoints.last() != QPointF( p2.x(), p2.y() ) )
4939 substringPoints << QPointF( p2.x(), p2.y() );
4942 distanceTraversed += *segmentLengthIt;
4943 if ( distanceTraversed > endDistance )
4950 if ( ( substringPoints.size() < 2 ) || ( substringPoints.size() == 2 && substringPoints.at( 0 ) == substringPoints.at( 1 ) ) )
4953 return substringPoints;
4958 double vertexAngle = M_PI - ( std::atan2( p3.y() - p2.y(), p3.x() - p2.x() ) - std::atan2( p2.y() - p1.y(), p2.x() - p1.x() ) );
4962 return vertexAngle < M_PI * 135.0 / 180.0 || vertexAngle > M_PI * 225.0 / 180.0;
4967 target.reserve( target.size() + line.size() );
4968 for (
const QPointF &pt : line )
4970 if ( !target.empty() && target.last() == pt )
4979 if ( fieldOrExpression.isEmpty() )
4982 auto expr = std::make_unique< QgsExpression >( fieldOrExpression );
4983 if ( !expr->hasParserError() )
4988 Q_ASSERT( !expr->hasParserError() );
5013 QList<double> breaks;
5016 breaks.append( maximum );
5020 const int minimumCount =
static_cast< int >( classes ) / 3;
5021 const double shrink = 0.75;
5022 const double highBias = 1.5;
5023 const double adjustBias = 0.5 + 1.5 * highBias;
5024 const int divisions = classes;
5025 const double h = highBias;
5028 const double dx = maximum - minimum;
5038 cell = std::max( std::fabs( minimum ), std::fabs( maximum ) );
5039 if ( adjustBias >= 1.5 * h + 0.5 )
5041 U = 1 + ( 1.0 / ( 1 + h ) );
5045 U = 1 + ( 1.5 / ( 1 + adjustBias ) );
5047 small = dx < ( cell * U * std::max( 1, divisions ) * 1e-07 * 3.0 );
5054 cell = 9 + cell / 10;
5055 cell = cell * shrink;
5057 if ( minimumCount > 1 )
5059 cell = cell / minimumCount;
5065 if ( divisions > 1 )
5067 cell = cell / divisions;
5070 if ( cell < 20 * 1e-07 )
5075 const double base = std::pow( 10.0, std::floor( std::log10( cell ) ) );
5077 if ( ( 2 * base ) - cell < h * ( cell - unit ) )
5080 if ( ( 5 * base ) - cell < adjustBias * ( cell - unit ) )
5083 if ( ( 10.0 * base ) - cell < h * ( cell - unit ) )
5090 int start = std::floor( minimum / unit + 1e-07 );
5091 int end = std::ceil( maximum / unit - 1e-07 );
5094 while ( start * unit > minimum + ( 1e-07 * unit ) )
5098 while ( end * unit < maximum - ( 1e-07 * unit ) )
5106 int k = std::floor( 0.5 + end - start );
5107 if ( k < minimumCount )
5109 k = minimumCount - k;
5113 start = start - k / 2 + k % 2;
5117 start = start - k / 2;
5118 end = end + k / 2 + k % 2;
5121 const double minimumBreak = start * unit;
5123 const int count = end - start;
5125 breaks.reserve( count );
5126 for (
int i = 1; i < count + 1; i++ )
5128 breaks.append( minimumBreak + i * unit );
5131 if ( breaks.isEmpty() )
5134 if ( breaks.first() < minimum )
5136 breaks[0] = minimum;
5138 if ( breaks.last() > maximum )
5140 breaks[breaks.count() - 1] = maximum;
5145 if ( minimum < 0.0 && maximum > 0.0 )
5147 QList<double> breaksMinusZero;
5148 for (
int i = 0; i < breaks.count(); i++ )
5150 breaksMinusZero.append( breaks[i] - 0.0 );
5153 for (
int i = 1; i < breaks.count(); i++ )
5155 if ( std::abs( breaksMinusZero[i] ) < std::abs( breaksMinusZero[i - 1] ) )
5158 breaks[posOfMin] = 0.0;
5167 bool roundToUnit =
false;
5170 if ( props.contains( u
"uomScale"_s ) )
5173 scale = props.value( u
"uomScale"_s ).toDouble( &ok );
5182 if ( props.value( u
"uom"_s ) ==
"http://www.opengeospatial.org/se/units/metre"_L1 )
5207 scale = 1 / 0.28 * 25.4;
5230 double rescaled = size * scale;
5235 rescaled = std::round( rescaled );
5242 const double x =
rescaleUom( point.x(), unit, props );
5243 const double y =
rescaleUom( point.y(), unit, props );
5244 return QPointF( x, y );
5249 QVector<qreal> result;
5250 QVector<qreal>::const_iterator it = array.constBegin();
5251 for ( ; it != array.constEnd(); ++it )
5253 result.append(
rescaleUom( *it, unit, props ) );
5260 if ( !props.value( u
"scaleMinDenom"_s, QString() ).toString().isEmpty() )
5262 QDomElement scaleMinDenomElem = doc.createElement( u
"se:MinScaleDenominator"_s );
5263 scaleMinDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( u
"scaleMinDenom"_s ).toString().toDouble() ) ) );
5264 ruleElem.appendChild( scaleMinDenomElem );
5267 if ( !props.value( u
"scaleMaxDenom"_s, QString() ).toString().isEmpty() )
5269 QDomElement scaleMaxDenomElem = doc.createElement( u
"se:MaxScaleDenominator"_s );
5270 scaleMaxDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( u
"scaleMaxDenom"_s ).toString().toDouble() ) ) );
5271 ruleElem.appendChild( scaleMaxDenomElem );
5280 const double parentScaleMinDenom = props.value( u
"scaleMinDenom"_s, u
"0"_s ).toString().toDouble( &ok );
5281 if ( !ok || parentScaleMinDenom <= 0 )
5282 props[u
"scaleMinDenom"_s] = QString::number( mScaleMinDenom );
5284 props[u
"scaleMinDenom"_s] = QString::number( std::max( parentScaleMinDenom, mScaleMinDenom ) );
5290 const double parentScaleMaxDenom = props.value( u
"scaleMaxDenom"_s, u
"0"_s ).toString().toDouble( &ok );
5291 if ( !ok || parentScaleMaxDenom <= 0 )
5292 props[u
"scaleMaxDenom"_s] = QString::number( mScaleMaxDenom );
5294 props[u
"scaleMaxDenom"_s] = QString::number( std::min( parentScaleMaxDenom, mScaleMaxDenom ) );
5302 if ( uom ==
"http://www.opengeospatial.org/se/units/metre"_L1 )
5304 scale = 1.0 / 0.00028;
5306 else if ( uom ==
"http://www.opengeospatial.org/se/units/foot"_L1 )
5308 scale = 304.8 / 0.28;
5315 return size * scale;
5324 SymbolLayerVisitor(
const QSet<QgsSymbolLayerId> &layerIds )
5325 : mSymbolLayerIds( layerIds )
5338 void visitSymbol(
const QgsSymbol *symbol,
const QString &identifier, QVector<int> rootPath )
5342 QVector<int> indexPath = rootPath;
5343 indexPath.append( idx );
5346 if ( mSymbolLayerIds.contains(
QgsSymbolLayerId( mCurrentRuleKey + identifier, indexPath ) ) )
5348 mSymbolLayers.insert( sl );
5354 visitSymbol( subSymbol, identifier, indexPath );
5363 if ( symbolEntity->symbol() )
5365 visitSymbol( symbolEntity->symbol(), leaf.
identifier, {} );
5371 QString mCurrentRuleKey;
5372 const QSet<QgsSymbolLayerId> &mSymbolLayerIds;
5373 QSet<const QgsSymbolLayer *> mSymbolLayers;
5377 SymbolLayerVisitor visitor( symbolLayerIds );
5378 renderer->
accept( &visitor );
5379 return visitor.mSymbolLayers;
5387 SymbolRefreshRateVisitor() {}
5398 void visitSymbol(
const QgsSymbol *symbol )
5415 if ( refreshRate == -1 || ( animatedMarker->frameRate() > refreshRate ) )
5416 refreshRate = animatedMarker->frameRate();
5420 visitSymbol( subSymbol );
5428 if (
QgsSymbol *symbol = qgis::down_cast<const QgsStyleSymbolEntity *>( leaf.
entity )->symbol() )
5430 visitSymbol( symbol );
5436 double refreshRate = -1;
5439 SymbolRefreshRateVisitor visitor;
5440 renderer->
accept( &visitor );
5441 return visitor.refreshRate;
5446 if ( !s || !context )
5472 size = markerSymbol->
size( *context );
5474 else if ( lineSymbol )
5476 size = lineSymbol->
width( *context );
5488 if ( minSize > 0 && size < minSize )
5492 else if ( maxSize > 0 && size > maxSize )
5504 std::unique_ptr< QgsMarkerSymbol > ms( markerSymbol->
clone() );
5505 ms->setSize( size );
5511 else if ( lineSymbol )
5513 std::unique_ptr< QgsLineSymbol > ls( lineSymbol->
clone() );
5514 ls->setWidth( size );
5526 QMap<QString, QgsProperty>::const_iterator paramIt = propertiesMap.constBegin();
5527 for ( ; paramIt != propertiesMap.constEnd(); ++paramIt )
5529 properties.insert( paramIt.key(), paramIt.value().valueAsString( context ) );
5536 angleRad = std::fmod( angleRad, M_PI * 2 );
5540 angleRad += M_PI * 2;
5544 struct rationalTangent
5556 static const QList<rationalTangent> __rationalTangents
5558 { 1, 57, 0.01754206006 },
5559 { 3, 86, 0.03486958155 },
5560 { 1, 19, 0.05258306161 },
5561 { 3, 43, 0.06965457373 },
5562 { 7, 80, 0.08727771295 },
5563 { 2, 19, 0.1048769387 },
5564 { 7, 57, 0.1221951707 },
5565 { 9, 64, 0.1397088743 },
5566 { 13, 82, 0.157228051 },
5567 { 3, 17, 0.174672199 },
5568 { 7, 36, 0.1920480172 },
5569 { 17, 80, 0.209385393 },
5570 { 3, 13, 0.2267988481 },
5571 { 1, 4, 0.2449786631 },
5572 { 26, 97, 0.2618852647 },
5573 { 27, 94, 0.2797041525 },
5574 { 26, 85, 0.2968446734 },
5575 { 13, 40, 0.3142318991 },
5576 { 21, 61, 0.3315541619 },
5577 { 4, 11, 0.3487710036 },
5578 { 38, 99, 0.3664967859 },
5579 { 40, 99, 0.383984624 },
5580 { 31, 73, 0.4015805401 },
5581 { 41, 92, 0.4192323938 },
5582 { 7, 15, 0.4366271598 },
5583 { 20, 41, 0.4538440015 },
5584 { 27, 53, 0.4711662643 },
5585 { 42, 79, 0.4886424026 },
5586 { 51, 92, 0.5061751436 },
5587 { 56, 97, 0.5235757641 },
5588 { 3, 5, 0.5404195003 },
5589 { 5, 8, 0.5585993153 },
5590 { 50, 77, 0.5759185996 },
5591 { 29, 43, 0.5933501462 },
5592 { 7, 10, 0.6107259644 },
5593 { 69, 95, 0.6281701124 },
5594 { 52, 69, 0.6458159195 },
5595 { 25, 32, 0.6632029927 },
5596 { 17, 21, 0.6805212247 },
5597 { 73, 87, 0.6981204504 },
5598 { 73, 84, 0.7154487784 },
5599 { 9, 10, 0.7328151018 },
5600 { 83, 89, 0.7505285818 },
5601 { 28, 29, 0.7678561033 },
5602 { 1, 1, 0.7853981634 },
5603 { 29, 28, 0.8029402235 },
5604 { 89, 83, 0.820267745 },
5605 { 10, 9, 0.837981225 },
5606 { 107, 93, 0.855284165 },
5607 { 87, 73, 0.8726758763 },
5608 { 121, 98, 0.8900374031 },
5609 { 32, 25, 0.9075933341 },
5610 { 69, 52, 0.9249804073 },
5611 { 128, 93, 0.9424647244 },
5612 { 10, 7, 0.9600703624 },
5613 { 43, 29, 0.9774461806 },
5614 { 77, 50, 0.9948777272 },
5615 { 8, 5, 1.012197011 },
5616 { 163, 98, 1.029475114 },
5617 { 168, 97, 1.047174539 },
5618 { 175, 97, 1.064668696 },
5619 { 126, 67, 1.082075603 },
5620 { 157, 80, 1.099534652 },
5621 { 203, 99, 1.117049384 },
5622 { 193, 90, 1.134452855 },
5623 { 146, 65, 1.151936673 },
5624 { 139, 59, 1.169382787 },
5625 { 99, 40, 1.186811703 },
5626 { 211, 81, 1.204257817 },
5627 { 272, 99, 1.221730164 },
5628 { 273, 94, 1.239188479 },
5629 { 277, 90, 1.25664606 },
5630 { 157, 48, 1.274088705 },
5631 { 279, 80, 1.291550147 },
5632 { 362, 97, 1.308990773 },
5633 { 373, 93, 1.326448578 },
5634 { 420, 97, 1.343823596 },
5635 { 207, 44, 1.361353157 },
5636 { 427, 83, 1.378810994 },
5637 { 414, 73, 1.396261926 },
5638 { 322, 51, 1.413716057 },
5639 { 185, 26, 1.431170275 },
5640 { 790, 97, 1.448623034 },
5641 { 333, 35, 1.466075711 },
5642 { 1063, 93, 1.483530284 },
5643 { 1330, 93, 1.500985147 },
5644 { 706, 37, 1.518436297 },
5645 { 315, 11, 1.535889876 },
5646 { 3953, 69, 1.553343002 },
5652 static const QList<rationalTangent> rationalTangents {
5653 { 1, 10, qDegreesToRadians( 5.71059 ) },
5654 { 1, 5, qDegreesToRadians( 11.3099 ) },
5655 { 1, 4, qDegreesToRadians( 14.0362 ) },
5656 { 1, 4, qDegreesToRadians( 18.4349 ) },
5657 { 1, 2, qDegreesToRadians( 26.5651 ) },
5658 { 2, 3, qDegreesToRadians( 33.6901 ) },
5659 { 1, 1, qDegreesToRadians( 45.0 ) },
5660 { 3, 2, qDegreesToRadians( 56.3099 ) },
5661 { 2, 1, qDegreesToRadians( 63.4349 ) },
5662 { 3, 1, qDegreesToRadians( 71.5651 ) },
5663 { 4, 1, qDegreesToRadians( 75.9638 ) },
5664 { 10, 1, qDegreesToRadians( 84.2894 ) },
5667 const int quadrant {
static_cast<int>( angleRad / M_PI_2 ) };
5668 Q_ASSERT( quadrant >= 0 && quadrant <= 3 );
5680 angleRad -= M_PI / 2;
5690 angleRad -= M_PI + M_PI_2;
5711 for (
int idx = 0; idx < rationalTangents.count(); ++idx )
5713 const auto item = rationalTangents.at( idx );
5714 if (
qgsDoubleNear( item.angle, angleRad, 10E-3 ) || item.angle > angleRad )
5721 const rationalTangent bTan { rationalTangents.at( rTanIdx ) };
5722 angleRad = bTan.angle;
5723 const double k { bTan.q * height * width / std::cos( angleRad ) };
5724 const int hcfH { std::gcd( bTan.p * height, bTan.q * width ) };
5725 const int hcfW { std::gcd( bTan.q * height, bTan.p * width ) };
5726 const int W1 {
static_cast<int>( std::round( k / hcfW ) ) };
5727 const int H1 {
static_cast<int>( std::round( k / hcfH ) ) };
5740 angleRad += M_PI / 2;
5753 angleRad += M_PI + M_PI_2;
5766 sl->
setId( generateId() );
5807 maskSl->clearMasks();
5810 if (
QgsSymbol *subSymbol = maskSl->subSymbol() )
5821 if ( clipGeometries.empty() )
5824 if ( bounds.isNull() )
5825 return clipGeometries;
5830 .erase( std::remove_if( clipGeometries.begin(), clipGeometries.end(), [&boundsRect](
const QgsGeometry &geometry ) { return !geometry.boundingBoxIntersects( boundsRect ); } ), clipGeometries.end() );
5832 return clipGeometries;
5842QList<QList<QgsSymbolLayerUtils::BlankSegments>> QgsSymbolLayerUtils::parseBlankSegments(
const QString &strBlankSegments,
const QgsRenderContext &renderContext,
Qgis::RenderUnit unit, QString &error )
5844 QString currentNumber;
5845 QList<QList<BlankSegments>> blankSegments;
5846 constexpr char internalError[] =
"Internal error while processing blank segments";
5848 auto appendLevel = [&blankSegments, &internalError](
int level ) ->
void {
5851 blankSegments.append( QList<BlankSegments>() );
5853 else if ( level == 1 )
5855 if ( blankSegments.isEmpty() )
5856 throw std::runtime_error( internalError );
5857 blankSegments.back().append( BlankSegments() );
5859 else if ( level == 2 )
5861 if ( blankSegments.isEmpty() || blankSegments.back().isEmpty() )
5862 throw std::runtime_error( internalError );
5863 blankSegments.back().back().append( QPair<double, double>( -1, -1 ) );
5866 throw std::runtime_error( internalError );
5869 auto addNumber = [&blankSegments, &internalError, ¤tNumber](
const QChar &
c ) ->
void {
5870 if ( blankSegments.isEmpty() || blankSegments.back().isEmpty() || blankSegments.back().back().isEmpty() )
5872 throw std::runtime_error( internalError );
5875 if ( (
c ==
')' ||
c ==
',' ) && blankSegments.back().back().back().first == -1 )
5877 throw std::runtime_error(
"Missing number" );
5880 if ( blankSegments.back().back().back().second != -1 )
5882 throw std::runtime_error(
"Too many number" );
5886 const double number = currentNumber.toDouble( &ok );
5889 throw std::runtime_error( u
"bad formatted number '%1'"_s.arg( currentNumber ).toStdString() );
5892 BlankSegments &segments = blankSegments.back().back();
5893 if ( segments.back().first == -1 )
5895 if ( segments.count() > 1 && segments.at( segments.count() - 2 ).second > number )
5896 throw std::runtime_error( u
"Wrong blank segments distances, start (%1) < previous end (%2)"_s.arg( number ).arg( segments.at( segments.count() - 2 ).second ).toStdString() );
5898 blankSegments.back().back().back().first = number;
5900 else if ( blankSegments.back().back().back().first > number )
5902 throw std::runtime_error( u
"Wrong blank segments distances, start (%1) > end (%2)"_s.arg( blankSegments.back().back().back().first ).arg( number ).toStdString() );
5906 blankSegments.back().back().back().second = number;
5908 currentNumber.clear();
5915 for (
const QChar &
c : strBlankSegments )
5917 if ( !currentNumber.isEmpty() && (
c.isSpace() ||
c ==
')' ||
c ==
',' ) )
5920 throw std::runtime_error(
"Missing '('" );
5927 throw std::runtime_error(
"Extraneous '('" );
5928 appendLevel( ++level );
5930 else if (
c ==
')' )
5933 throw std::runtime_error(
"Extraneous ')'" );
5934 if ( level == 2 && !blankSegments.isEmpty() && !blankSegments.back().isEmpty() && blankSegments.back().back().count() == 1 && blankSegments.back().back().back() == QPair<double, double>( -1, -1 ) )
5936 blankSegments.back().back().pop_back();
5940 else if (
c ==
',' )
5942 if ( ( level == 0 && blankSegments.count() == 0 )
5943 || ( level == 1 && !blankSegments.isEmpty() && blankSegments.back().count() == 0 )
5944 || ( level == 2 && !blankSegments.isEmpty() && !blankSegments.back().isEmpty() && blankSegments.back().back().count() == 0 ) )
5945 throw std::runtime_error(
"No elements, Not expecting ','" );
5947 appendLevel( level );
5949 else if (
c.isNumber() ||
c ==
'.' )
5951 currentNumber.append(
c );
5953 else if ( !
c.isSpace() )
5955 throw std::runtime_error( u
"Invalid character '%1'"_s.arg(
c ).toStdString() );
5961 throw std::runtime_error(
"Missing ')'" );
5964 catch (
const std::exception &e )
5966 blankSegments.clear();
5967 error = u
"%1 (column: %2)"_s.arg( e.what() ).arg( iChar );
5971 std::for_each( blankSegments.begin(), blankSegments.end(), [&renderContext, &unit]( QList<BlankSegments> &rings ) {
5972 std::for_each( rings.begin(), rings.end(), [&renderContext, &unit]( BlankSegments &blankSegments ) {
5973 std::for_each( blankSegments.begin(), blankSegments.end(), [&renderContext, &unit]( QPair<double, double> &blankSegment ) {
5974 blankSegment.first = renderContext.convertToPainterUnits( blankSegment.first, unit );
5975 blankSegment.second = renderContext.convertToPainterUnits( blankSegment.second, unit );
5980 return blankSegments;
5983QgsSymbolLayerUtils::ExtraItems QgsSymbolLayerUtils::parseExtraItems(
const QString &strExtraItems, QString &error )
5985 QString currentNumber;
5986 ExtraItems extraItems;
5989 auto addNumber = [&extraItems, ¤tNumber, &nbNumbers](
const QChar &
c ) -> QString {
5990 if (
c ==
',' && nbNumbers == 0 )
5992 return u
"Missing number"_s;
5994 else if ( nbNumbers >= 3 )
5996 return u
"Too many number"_s;
6001 const double number = currentNumber.toDouble( &ok );
6004 return u
"bad formatted number '%1'"_s.arg( currentNumber );
6008 switch ( nbNumbers )
6011 extraItems.append( { { number, 0 }, 0 } );
6015 extraItems.back().first.setY( number );
6019 if ( number < 0 || number > 360 )
6021 return u
"Angle must be between 0° and 360°"_s;
6024 extraItems.back().second = number;
6028 return u
"Too many number"_s;
6032 currentNumber.clear();
6040 for (
const QChar &
c : strExtraItems )
6042 if ( !currentNumber.isEmpty() && (
c.isSpace() ||
c ==
',' ) )
6044 error = addNumber(
c );
6047 if ( !error.isEmpty() )
6054 if ( extraItems.count() == 0 )
6056 error = u
"No elements, Not expecting ','"_s;
6060 else if (
c.isNumber() ||
c ==
'.' ||
c ==
'-' )
6062 currentNumber.append(
c );
6064 else if ( !
c.isSpace() )
6066 error = u
"Invalid character '%1'"_s.arg(
c );
6069 if ( !error.isEmpty() )
6078 if ( error.isEmpty() && !currentNumber.isEmpty() )
6080 error = addNumber(
' ' );
6083 if ( error.isEmpty() && nbNumbers != 0 && nbNumbers != 3 )
6085 error = u
"Missing number"_s;
6088 if ( !error.isEmpty() )
6091 error += u
" (column: %1)"_s.arg( iChar );
@ 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.
@ HeadSingle
One single head at the end.
@ HeadReversed
One single head at the beginning.
ArrowType
Possible arrow types.
@ ArrowRightHalf
Halved arrow, only the right side of the arrow is rendered (for straight arrows) or the side toward t...
@ ArrowPlain
Regular arrow.
@ ArrowLeftHalf
Halved arrow, only the left side of the arrow is rendered (for straight arrows) or the side toward th...
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 QString typeString()
Returns the string identifier for QgsCptCityColorRamp.
static std::unique_ptr< QgsColorRamp > create(const QVariantMap &properties=QVariantMap())
Creates the symbol layer.
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 std::vector< std::unique_ptr< 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, QgsFeedback *feedback=nullptr) 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 std::unique_ptr< 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.
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.
int numPoints() const override
Returns the number of points in the curve.
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.
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)
Decodes a string to a color.
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< QMimeData > colorListToMimeData(const QgsNamedColorList &colorList, bool allFormats=true)
Creates mime data from a list of named colors.
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 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 std::unique_ptr< QMimeData > symbolToMimeData(const QgsSymbol *symbol)
Creates new mime data from a symbol.
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)
Lossy-encodes a color to a string.
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 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 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)
static std::unique_ptr< QMimeData > colorToMimeData(const QColor &color)
Creates mime data from a color.
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)
constexpr QgsDataDefinedStringDecoder< V, N > makeDataDefinedStringDecoder(const DataDefinedDecoderEntry< V >(&values)[N])
Creates a QgsDataDefinedStringDecoder from a hardcoded lookup table.
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.