51#include <QDomDocument>
61#include <QRegularExpression>
64#define POINTS_TO_MM 2.83464567
68 return QStringLiteral(
"%1,%2,%3,%4" ).arg( color.red() ).arg( color.green() ).arg( color.blue() ).arg( color.alpha() );
73 const QStringList lst =
str.split(
',' );
74 if ( lst.count() < 3 )
78 int red, green, blue, alpha;
80 green = lst[1].toInt();
81 blue = lst[2].toInt();
83 if ( lst.count() > 3 )
85 alpha = lst[3].toInt();
87 return QColor( red, green, blue, alpha );
92 return QString::number( alpha / 255.0,
'g', 2 );
98 double alpha =
str.toDouble( &ok );
99 if ( !ok || alpha > 1 )
101 else if ( alpha < 0 )
110 case QFont::StyleNormal:
111 return QStringLiteral(
"normal" );
112 case QFont::StyleItalic:
113 return QStringLiteral(
"italic" );
114 case QFont::StyleOblique:
115 return QStringLiteral(
"oblique" );
123 if (
str == QLatin1String(
"normal" ) )
return QFont::StyleNormal;
124 if (
str == QLatin1String(
"italic" ) )
return QFont::StyleItalic;
125 if (
str == QLatin1String(
"oblique" ) )
return QFont::StyleOblique;
126 return QFont::StyleNormal;
131 if ( weight == 50 )
return QStringLiteral(
"normal" );
132 if ( weight == 75 )
return QStringLiteral(
"bold" );
136 if ( weight < 0 )
return QStringLiteral(
"100" );
137 if ( weight > 99 )
return QStringLiteral(
"900" );
138 return QString::number( weight * 800 / 99 + 100 );
144 const int weight =
str.toInt( &ok );
146 return static_cast< int >( QFont::Normal );
150 if ( weight > 900 )
return 99;
151 if ( weight < 100 )
return 0;
152 return ( weight - 100 ) * 99 / 800;
160 return QStringLiteral(
"no" );
162 return QStringLiteral(
"solid" );
164 return QStringLiteral(
"dash" );
166 return QStringLiteral(
"dot" );
167 case Qt::DashDotLine:
168 return QStringLiteral(
"dash dot" );
169 case Qt::DashDotDotLine:
170 return QStringLiteral(
"dash dot dot" );
172 return QStringLiteral(
"???" );
178 if (
str == QLatin1String(
"no" ) )
return Qt::NoPen;
179 if (
str == QLatin1String(
"solid" ) )
return Qt::SolidLine;
180 if (
str == QLatin1String(
"dash" ) )
return Qt::DashLine;
181 if (
str == QLatin1String(
"dot" ) )
return Qt::DotLine;
182 if (
str == QLatin1String(
"dash dot" ) )
return Qt::DashDotLine;
183 if (
str == QLatin1String(
"dash dot dot" ) )
return Qt::DashDotDotLine;
184 return Qt::SolidLine;
192 return QStringLiteral(
"bevel" );
194 return QStringLiteral(
"miter" );
196 return QStringLiteral(
"round" );
198 return QStringLiteral(
"???" );
204 const QString cleaned =
str.toLower().trimmed();
205 if ( cleaned == QLatin1String(
"bevel" ) )
206 return Qt::BevelJoin;
207 if ( cleaned == QLatin1String(
"miter" ) )
208 return Qt::MiterJoin;
209 if ( cleaned == QLatin1String(
"round" ) )
210 return Qt::RoundJoin;
211 return Qt::BevelJoin;
219 return QStringLiteral(
"bevel" );
221 return QStringLiteral(
"mitre" );
223 return QStringLiteral(
"round" );
231 if (
str == QLatin1String(
"bevel" ) )
return Qt::BevelJoin;
232 if (
str == QLatin1String(
"mitre" ) )
return Qt::MiterJoin;
233 if (
str == QLatin1String(
"round" ) )
return Qt::RoundJoin;
234 return Qt::BevelJoin;
242 return QStringLiteral(
"square" );
244 return QStringLiteral(
"flat" );
246 return QStringLiteral(
"round" );
248 return QStringLiteral(
"???" );
254 if (
str == QLatin1String(
"square" ) )
return Qt::SquareCap;
255 if (
str == QLatin1String(
"flat" ) )
return Qt::FlatCap;
256 if (
str == QLatin1String(
"round" ) )
return Qt::RoundCap;
257 return Qt::SquareCap;
265 return QStringLiteral(
"square" );
267 return QStringLiteral(
"butt" );
269 return QStringLiteral(
"round" );
277 if (
str == QLatin1String(
"square" ) )
return Qt::SquareCap;
278 if (
str == QLatin1String(
"butt" ) )
return Qt::FlatCap;
279 if (
str == QLatin1String(
"round" ) )
return Qt::RoundCap;
280 return Qt::SquareCap;
287 case Qt::SolidPattern :
288 return QStringLiteral(
"solid" );
289 case Qt::HorPattern :
290 return QStringLiteral(
"horizontal" );
291 case Qt::VerPattern :
292 return QStringLiteral(
"vertical" );
293 case Qt::CrossPattern :
294 return QStringLiteral(
"cross" );
295 case Qt::BDiagPattern :
296 return QStringLiteral(
"b_diagonal" );
297 case Qt::FDiagPattern :
298 return QStringLiteral(
"f_diagonal" );
299 case Qt::DiagCrossPattern :
300 return QStringLiteral(
"diagonal_x" );
301 case Qt::Dense1Pattern :
302 return QStringLiteral(
"dense1" );
303 case Qt::Dense2Pattern :
304 return QStringLiteral(
"dense2" );
305 case Qt::Dense3Pattern :
306 return QStringLiteral(
"dense3" );
307 case Qt::Dense4Pattern :
308 return QStringLiteral(
"dense4" );
309 case Qt::Dense5Pattern :
310 return QStringLiteral(
"dense5" );
311 case Qt::Dense6Pattern :
312 return QStringLiteral(
"dense6" );
313 case Qt::Dense7Pattern :
314 return QStringLiteral(
"dense7" );
316 return QStringLiteral(
"no" );
318 return QStringLiteral(
"???" );
324 if (
str == QLatin1String(
"solid" ) )
return Qt::SolidPattern;
325 if (
str == QLatin1String(
"horizontal" ) )
return Qt::HorPattern;
326 if (
str == QLatin1String(
"vertical" ) )
return Qt::VerPattern;
327 if (
str == QLatin1String(
"cross" ) )
return Qt::CrossPattern;
328 if (
str == QLatin1String(
"b_diagonal" ) )
return Qt::BDiagPattern;
329 if (
str == QLatin1String(
"f_diagonal" ) )
return Qt::FDiagPattern;
330 if (
str == QLatin1String(
"diagonal_x" ) )
return Qt::DiagCrossPattern;
331 if (
str == QLatin1String(
"dense1" ) )
return Qt::Dense1Pattern;
332 if (
str == QLatin1String(
"dense2" ) )
return Qt::Dense2Pattern;
333 if (
str == QLatin1String(
"dense3" ) )
return Qt::Dense3Pattern;
334 if (
str == QLatin1String(
"dense4" ) )
return Qt::Dense4Pattern;
335 if (
str == QLatin1String(
"dense5" ) )
return Qt::Dense5Pattern;
336 if (
str == QLatin1String(
"dense6" ) )
return Qt::Dense6Pattern;
337 if (
str == QLatin1String(
"dense7" ) )
return Qt::Dense7Pattern;
338 if (
str == QLatin1String(
"no" ) )
return Qt::NoBrush;
339 return Qt::SolidPattern;
346 case Qt::CrossPattern:
347 return QStringLiteral(
"cross" );
348 case Qt::DiagCrossPattern:
349 return QStringLiteral(
"x" );
356 return QStringLiteral(
"horline" );
358 return QStringLiteral(
"line" );
359 case Qt::BDiagPattern:
360 return QStringLiteral(
"slash" );
361 case Qt::FDiagPattern:
362 return QStringLiteral(
"backslash" );
365 case Qt::Dense1Pattern:
366 case Qt::Dense2Pattern:
367 case Qt::Dense3Pattern:
368 case Qt::Dense4Pattern:
369 case Qt::Dense5Pattern:
370 case Qt::Dense6Pattern:
371 case Qt::Dense7Pattern:
381 if (
str == QLatin1String(
"horline" ) )
return Qt::HorPattern;
382 if (
str == QLatin1String(
"line" ) )
return Qt::VerPattern;
383 if (
str == QLatin1String(
"cross" ) )
return Qt::CrossPattern;
384 if (
str == QLatin1String(
"slash" ) )
return Qt::BDiagPattern;
385 if (
str == QLatin1String(
"backshash" ) )
return Qt::FDiagPattern;
386 if (
str == QLatin1String(
"x" ) )
return Qt::DiagCrossPattern;
388 if (
str.startsWith( QLatin1String(
"brush://" ) ) )
396 const QString compareString =
string.trimmed();
400 if ( compareString.compare( QLatin1String(
"feature" ), Qt::CaseInsensitive ) == 0 )
402 else if ( compareString.compare( QLatin1String(
"viewport" ), Qt::CaseInsensitive ) == 0 )
412 switch ( coordinateReference )
415 return QStringLiteral(
"feature" );
417 return QStringLiteral(
"viewport" );
428 const QString s = value.toString().toLower().trimmed();
429 if ( s == QLatin1String(
"single" ) )
431 else if ( s == QLatin1String(
"reversed" ) )
433 else if ( s == QLatin1String(
"double" ) )
435 else if ( value.toInt() == 1 )
437 else if ( value.toInt() == 2 )
439 else if ( value.toInt( &intOk ) == 0 && intOk )
453 const QString s = value.toString().toLower().trimmed();
454 if ( s == QLatin1String(
"plain" ) )
456 else if ( s == QLatin1String(
"lefthalf" ) )
458 else if ( s == QLatin1String(
"righthalf" ) )
460 else if ( value.toInt() == 1 )
462 else if ( value.toInt() == 2 )
464 else if ( value.toInt( &intOk ) == 0 && intOk )
474 const QString compareString =
string.trimmed();
478 if ( compareString.compare( QLatin1String(
"no" ), Qt::CaseInsensitive ) == 0 )
480 else if ( compareString.compare( QLatin1String(
"shape" ), Qt::CaseInsensitive ) == 0 )
482 else if ( compareString.compare( QLatin1String(
"centroid_within" ), Qt::CaseInsensitive ) == 0 )
484 else if ( compareString.compare( QLatin1String(
"completely_within" ), Qt::CaseInsensitive ) == 0 )
497 return QStringLiteral(
"no" );
499 return QStringLiteral(
"shape" );
501 return QStringLiteral(
"centroid_within" );
503 return QStringLiteral(
"completely_within" );
510 const QString compareString =
string.trimmed();
514 if ( compareString.compare( QLatin1String(
"no" ), Qt::CaseInsensitive ) == 0 )
516 else if ( compareString.compare( QLatin1String(
"during_render" ), Qt::CaseInsensitive ) == 0 )
518 else if ( compareString.compare( QLatin1String(
"before_render" ), Qt::CaseInsensitive ) == 0 )
531 return QStringLiteral(
"no" );
533 return QStringLiteral(
"during_render" );
535 return QStringLiteral(
"before_render" );
547 QStringList lst =
str.split(
',' );
548 if ( lst.count() != 2 )
549 return QPointF( 0, 0 );
550 return QPointF( lst[0].toDouble(), lst[1].toDouble() );
561 if ( value.userType() == QMetaType::Type::QVariantList )
563 const QVariantList list = value.toList();
564 if ( list.size() != 2 )
568 bool convertOk =
false;
569 const double x = list.at( 0 ).toDouble( &convertOk );
572 const double y = list.at( 1 ).toDouble( &convertOk );
577 return QPointF( x, y );
585 const QStringList list = value.toString().trimmed().split(
',' );
586 if ( list.count() != 2 )
588 bool convertOk =
false;
589 const double x = list.at( 0 ).toDouble( &convertOk );
592 const double y = list.at( 1 ).toDouble( &convertOk );
597 return QPointF( x, y );
611 QStringList lst =
string.split(
',' );
612 if ( lst.count() != 2 )
613 return QSizeF( 0, 0 );
614 return QSizeF( lst[0].toDouble(), lst[1].toDouble() );
625 if ( value.userType() == QMetaType::Type::QVariantList )
627 const QVariantList list = value.toList();
628 if ( list.size() != 2 )
632 bool convertOk =
false;
633 const double x = list.at( 0 ).toDouble( &convertOk );
636 const double y = list.at( 1 ).toDouble( &convertOk );
641 return QSizeF( x, y );
649 const QStringList list = value.toString().trimmed().split(
',' );
650 if ( list.count() != 2 )
652 bool convertOk =
false;
653 const double x = list.at( 0 ).toDouble( &convertOk );
656 const double y = list.at( 1 ).toDouble( &convertOk );
661 return QSizeF( x, y );
682 if (
str.startsWith( QLatin1String(
"3x:" ) ) )
685 const QString chopped =
str.mid( 3 );
686 lst = chopped.split(
',' );
690 lst =
str.split(
',' );
692 if ( lst.count() < 2 )
695 double minScale = lst[0].toDouble();
697 minScale = minScale != 0 ? 1.0 / minScale : 0;
698 double maxScale = lst[1].toDouble();
700 maxScale = maxScale != 0 ? 1.0 / maxScale : 0;
702 if ( lst.count() < 6 )
722 *scaleFactor = 0.001;
723 return QStringLiteral(
"http://www.opengeospatial.org/se/units/metre" );
728 return QStringLiteral(
"http://www.opengeospatial.org/se/units/metre" );
735 *scaleFactor = 1 / 0.28;
744 if (
str == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
750 else if (
str == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
753 *scaleFactor = 0.3048;
768 QString vectorString;
769 QVector<qreal>::const_iterator it = v.constBegin();
770 for ( ; it != v.constEnd(); ++it )
772 if ( it != v.constBegin() )
774 vectorString.append(
';' );
776 vectorString.append( QString::number( *it ) );
783 QVector<qreal> resultVector;
785 const QStringList realList = s.split(
';' );
786 QStringList::const_iterator it = realList.constBegin();
787 for ( ; it != realList.constEnd(); ++it )
789 resultVector.append( it->toDouble() );
797 QString vectorString;
798 QVector<qreal>::const_iterator it = v.constBegin();
799 for ( ; it != v.constEnd(); ++it )
801 if ( it != v.constBegin() )
803 vectorString.append(
' ' );
805 vectorString.append( QString::number( *it ) );
812 QVector<qreal> resultVector;
814 const QStringList realList = s.split(
' ' );
815 QStringList::const_iterator it = realList.constBegin();
816 for ( ; it != realList.constEnd(); ++it )
818 resultVector.append( it->toDouble() );
826 QString encodedValue;
828 switch ( scaleMethod )
831 encodedValue = QStringLiteral(
"diameter" );
834 encodedValue = QStringLiteral(
"area" );
844 if (
str == QLatin1String(
"diameter" ) )
858 if ( s.compare( QLatin1String(
"Lighten" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Lighten;
859 if ( s.compare( QLatin1String(
"Screen" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Screen;
860 if ( s.compare( QLatin1String(
"Dodge" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorDodge;
861 if ( s.compare( QLatin1String(
"Addition" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Plus;
862 if ( s.compare( QLatin1String(
"Darken" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Darken;
863 if ( s.compare( QLatin1String(
"Multiply" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Multiply;
864 if ( s.compare( QLatin1String(
"Burn" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorBurn;
865 if ( s.compare( QLatin1String(
"Overlay" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Overlay;
866 if ( s.compare( QLatin1String(
"SoftLight" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_SoftLight;
867 if ( s.compare( QLatin1String(
"HardLight" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_HardLight;
868 if ( s.compare( QLatin1String(
"Difference" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Difference;
869 if ( s.compare( QLatin1String(
"Subtract" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Exclusion;
870 return QPainter::CompositionMode_SourceOver;
875 return QIcon(
symbolPreviewPixmap( symbol, size, padding,
nullptr,
false,
nullptr, shape, screen ) );
883 QPixmap pixmap( size * devicePixelRatio );
884 pixmap.setDevicePixelRatio( devicePixelRatio );
886 pixmap.fill( Qt::transparent );
888 painter.begin( &pixmap );
893 painter.setRenderHint( QPainter::Antialiasing );
894 painter.setRenderHint( QPainter::SmoothPixmapTransform );
904 size.setWidth( size.rwidth() - ( padding * 2 ) );
905 size.setHeight( size.rheight() - ( padding * 2 ) );
906 painter.translate( padding, padding );
916 std::unique_ptr<QgsSymbol> symbol_noDD( symbol->
clone( ) );
918 for (
const auto &layer : layers )
920 for (
int i = 0; i < layer->dataDefinedProperties().count(); ++i )
922 QgsProperty &prop = layer->dataDefinedProperties().property( i );
928 symbol_noDD->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape, screen );
932 std::unique_ptr<QgsSymbol> symbolClone( symbol->
clone( ) );
933 symbolClone->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape, screen );
947 maxBleed = layerMaxBleed > maxBleed ? layerMaxBleed : maxBleed;
957 painter.begin( &picture );
958 painter.setRenderHint( QPainter::Antialiasing );
968 switch ( parentSymbolType )
983 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
984 layerClone->drawPreviewIcon( symbolContext, size );
992 QPixmap pixmap( size * devicePixelRatio );
993 pixmap.setDevicePixelRatio( devicePixelRatio );
994 pixmap.fill( Qt::transparent );
996 painter.begin( &pixmap );
997 painter.setRenderHint( QPainter::Antialiasing );
1015 switch ( parentSymbolType )
1030 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
1031 layerClone->drawPreviewIcon( symbolContext, size );
1033 return QIcon( pixmap );
1043 QPixmap pixmap( size );
1044 pixmap.fill( Qt::transparent );
1047 painter.begin( &pixmap );
1050 if ( drawTransparentBackground )
1051 drawStippledBackground( &painter, QRect( padding, padding, size.width() - padding * 2, size.height() - padding * 2 ) );
1055 switch ( direction )
1057 case Qt::Horizontal:
1059 for (
int i = 0; i < size.width(); i++ )
1061 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.width() ) );
1062 painter.setPen( pen );
1063 const int x = flipDirection ? size.width() - i - 1 : i;
1064 painter.drawLine( x, 0 + padding, x, size.height() - 1 - padding );
1071 for (
int i = 0; i < size.height(); i++ )
1073 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.height() ) );
1074 painter.setPen( pen );
1075 const int y = flipDirection ? size.height() - i - 1 : i;
1076 painter.drawLine( 0 + padding, y, size.width() - 1 - padding, y );
1089 uchar pixDataRGB[] = { 255, 255, 255, 255,
1094 const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
1096 const int width = ( rect.width() < rect.height() ) ?
1097 rect.width() / 2.5 : rect.height() / 2.5;
1098 const QPixmap pix = QPixmap::fromImage( img.scaled( width, width ) );
1101 brush.setTexture( pix );
1102 painter->fillRect( rect, brush );
1107 const qreal s = ( markerSize - 1 ) / 2.0;
1112 p.setPen( QColor( 50, 100, 120, 200 ) );
1113 p.setBrush( QColor( 200, 200, 210, 120 ) );
1114 p.drawEllipse( x - s, y - s, s * 2, s * 2 );
1117 p.setPen( QColor( 255, 0, 0 ) );
1118 p.drawLine( x - s, y + s, x + s, y - s );
1119 p.drawLine( x - s, y - s, x + s, y + s );
1131static QPolygonF makeOffsetGeometry(
const QgsPolylineXY &polyline )
1133 int i, pointCount = polyline.count();
1135 QPolygonF resultLine;
1136 resultLine.resize( pointCount );
1140 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1141 resultLine[i] = QPointF( tempPtr->
x(), tempPtr->
y() );
1145static QList<QPolygonF> makeOffsetGeometry(
const QgsPolygonXY &polygon )
1147 QList<QPolygonF> resultGeom;
1148 resultGeom.reserve( polygon.size() );
1149 for (
int ring = 0; ring < polygon.size(); ++ring )
1150 resultGeom.append( makeOffsetGeometry( polygon[ ring ] ) );
1156 QList<QPolygonF> resultLine;
1158 if ( polyline.count() < 2 )
1160 resultLine.append( polyline );
1164 unsigned int i, pointCount = polyline.count();
1167 QPointF *tempPtr = polyline.data();
1168 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1169 tempPolyline[i] =
QgsPointXY( tempPtr->rx(), tempPtr->ry() );
1172 if ( !tempGeometry.
isNull() )
1174 const int quadSegments = 0;
1175 const double miterLimit = 2.0;
1183 if ( !offsetGeom.
isNull() )
1185 tempGeometry = offsetGeom;
1190 resultLine.append( makeOffsetGeometry( line ) );
1195 resultLine.append( makeOffsetGeometry( tempGeometry.
asPolygon() ) );
1201 resultLine.reserve( tempMPolyline.count() );
1202 for (
int part = 0; part < tempMPolyline.count(); ++part )
1204 resultLine.append( makeOffsetGeometry( tempMPolyline[ part ] ) );
1211 resultLine.reserve( tempMPolygon.count() );
1212 for (
int part = 0; part < tempMPolygon.count(); ++part )
1214 resultLine.append( makeOffsetGeometry( tempMPolygon[ part ] ) );
1222 resultLine.append( polyline );
1231 if ( element.isNull() )
1235 QDomNode layerNode = element.firstChild();
1237 while ( !layerNode.isNull() )
1239 QDomElement e = layerNode.toElement();
1240 if ( !e.isNull() && e.tagName() != QLatin1String(
"data_defined_properties" ) && e.tagName() != QLatin1String(
"buffer" ) )
1242 if ( e.tagName() != QLatin1String(
"layer" ) )
1251 const QDomElement s = e.firstChildElement( QStringLiteral(
"symbol" ) );
1254 std::unique_ptr< QgsSymbol > subSymbol(
loadSymbol( s, context ) );
1261 layers.append( layer );
1263 for (
int i = 0; i < subSymbol->symbolLayerCount(); ++i )
1265 layers.append( subSymbol->symbolLayer( i )->clone() );
1270 const bool res = layer->setSubSymbol( subSymbol.release() );
1273 QgsDebugError( QStringLiteral(
"symbol layer refused subsymbol: " ) + s.attribute(
"name" ) );
1275 layers.append( layer );
1280 layers.append( layer );
1285 layerNode = layerNode.nextSibling();
1288 if ( layers.isEmpty() )
1294 const QString symbolType = element.attribute( QStringLiteral(
"type" ) );
1297 if ( symbolType == QLatin1String(
"line" ) )
1299 else if ( symbolType == QLatin1String(
"fill" ) )
1301 else if ( symbolType == QLatin1String(
"marker" ) )
1309 if ( element.hasAttribute( QStringLiteral(
"outputUnit" ) ) )
1313 if ( element.hasAttribute( ( QStringLiteral(
"mapUnitScale" ) ) ) )
1316 const double oldMin = element.attribute( QStringLiteral(
"mapUnitMinScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1317 mapUnitScale.
minScale = oldMin != 0 ? 1.0 / oldMin : 0;
1318 const double oldMax = element.attribute( QStringLiteral(
"mapUnitMaxScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1319 mapUnitScale.
maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
1322 symbol->
setOpacity( element.attribute( QStringLiteral(
"alpha" ), QStringLiteral(
"1.0" ) ).toDouble() );
1323 symbol->
setClipFeaturesToExtent( element.attribute( QStringLiteral(
"clip_to_extent" ), QStringLiteral(
"1" ) ).toInt() );
1324 symbol->
setForceRHR( element.attribute( QStringLiteral(
"force_rhr" ), QStringLiteral(
"0" ) ).toInt() );
1326 if ( element.attribute( QStringLiteral(
"renderer_should_use_levels" ), QStringLiteral(
"0" ) ).toInt() )
1333 if ( !element.firstChildElement( QStringLiteral(
"buffer" ) ).isNull() )
1335 std::unique_ptr< QgsSymbolBufferSettings > bufferSettings = std::make_unique< QgsSymbolBufferSettings >();
1336 bufferSettings->readXml( element, context );
1344 const QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1345 if ( !ddProps.isNull() )
1355 const QString layerClass = element.attribute( QStringLiteral(
"class" ) );
1356 const bool locked = element.attribute( QStringLiteral(
"locked" ) ).toInt();
1357 const bool enabled = element.attribute( QStringLiteral(
"enabled" ), QStringLiteral(
"1" ) ).toInt();
1358 const int pass = element.attribute( QStringLiteral(
"pass" ) ).toInt();
1359 const QString
id = element.attribute( QStringLiteral(
"id" ) );
1380 if ( !
id.isEmpty() )
1384 const QDomElement effectElem = element.firstChildElement( QStringLiteral(
"effect" ) );
1385 if ( !effectElem.isNull() )
1393 const QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1394 if ( !ddProps.isNull() )
1401 const QSet< int > oldKeys = prevProperties.
propertyKeys();
1402 for (
int key : oldKeys )
1423 return QStringLiteral(
"line" );
1425 return QStringLiteral(
"marker" );
1427 return QStringLiteral(
"fill" );
1436 QDomElement symEl = doc.createElement( QStringLiteral(
"symbol" ) );
1437 symEl.setAttribute( QStringLiteral(
"type" ), _nameForSymbolType( symbol->
type() ) );
1438 symEl.setAttribute( QStringLiteral(
"name" ), name );
1439 symEl.setAttribute( QStringLiteral(
"alpha" ), QString::number( symbol->
opacity() ) );
1440 symEl.setAttribute( QStringLiteral(
"clip_to_extent" ), symbol->
clipFeaturesToExtent() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1441 symEl.setAttribute( QStringLiteral(
"force_rhr" ), symbol->
forceRHR() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1443 symEl.setAttribute( QStringLiteral(
"renderer_should_use_levels" ), QStringLiteral(
"1" ) );
1445 symEl.setAttribute( QStringLiteral(
"is_animated" ), symbol->
animationSettings().
isAnimated() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1449 bufferSettings->writeXml( symEl, context );
1453 QDomElement ddProps = doc.createElement( QStringLiteral(
"data_defined_properties" ) );
1455 symEl.appendChild( ddProps );
1461 QDomElement layerEl = doc.createElement( QStringLiteral(
"layer" ) );
1462 layerEl.setAttribute( QStringLiteral(
"class" ), layer->
layerType() );
1463 layerEl.setAttribute( QStringLiteral(
"enabled" ), layer->
enabled() );
1464 layerEl.setAttribute( QStringLiteral(
"locked" ), layer->
isLocked() );
1465 layerEl.setAttribute( QStringLiteral(
"pass" ), layer->
renderingPass() );
1466 layerEl.setAttribute( QStringLiteral(
"id" ), layer->
id() );
1480 QDomElement ddProps = doc.createElement( QStringLiteral(
"data_defined_properties" ) );
1482 layerEl.appendChild( ddProps );
1486 const QString subname = QStringLiteral(
"@%1@%2" ).arg( name ).arg( i );
1487 const QDomElement subEl =
saveSymbol( subname, subSymbol, doc, context );
1488 layerEl.appendChild( subEl );
1490 symEl.appendChild( layerEl );
1498 QDomDocument doc( QStringLiteral(
"qgis-symbol-definition" ) );
1501 QTextStream stream( &props );
1502 symbolElem.save( stream, -1 );
1508 QList<QgsSymbolLayer *> &layers )
1512 if ( element.isNull() )
1517 const QString symbolizerName = element.localName();
1519 if ( symbolizerName == QLatin1String(
"PointSymbolizer" ) )
1522 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1523 if ( graphicElem.isNull() )
1525 QgsDebugError( QStringLiteral(
"Graphic element not found in PointSymbolizer" ) );
1561 if ( symbolizerName == QLatin1String(
"LineSymbolizer" ) )
1564 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1565 if ( strokeElem.isNull() )
1567 QgsDebugError( QStringLiteral(
"Stroke element not found in LineSymbolizer" ) );
1597 if ( symbolizerName == QLatin1String(
"PolygonSymbolizer" ) )
1600 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1601 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1602 if ( fillElem.isNull() && strokeElem.isNull() )
1604 QgsDebugError( QStringLiteral(
"neither Fill nor Stroke element not found in PolygonSymbolizer" ) );
1622 if ( l->
layerType() == QLatin1String(
"SimpleFill" ) || l->
layerType() == QLatin1String(
"SVGFill" ) )
1658 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1659 if ( fillElem.isNull() )
1661 QgsDebugError( QStringLiteral(
"Fill element not found" ) );
1683 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1684 if ( strokeElem.isNull() )
1686 QgsDebugError( QStringLiteral(
"Stroke element not found" ) );
1702 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1703 if ( graphicElem.isNull() )
1705 QgsDebugError( QStringLiteral(
"Graphic element not found" ) );
1730 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1731 if ( graphicElem.isNull() )
1734 const QDomElement externalGraphicElem = graphicElem.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
1735 if ( externalGraphicElem.isNull() )
1739 const QDomElement formatElem = externalGraphicElem.firstChildElement( QStringLiteral(
"Format" ) );
1740 if ( formatElem.isNull() )
1743 const QString elementFormat = formatElem.firstChild().nodeValue();
1744 if ( ! format.isEmpty() && elementFormat != format )
1746 QgsDebugMsgLevel(
"unsupported External Graphic format found: " + elementFormat, 4 );
1751 const QDomElement onlineResourceElem = externalGraphicElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1752 const QDomElement inlineContentElem = externalGraphicElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1753 if ( !onlineResourceElem.isNull() )
1758 else if ( !inlineContentElem.isNull() )
1771 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1772 if ( graphicElem.isNull() )
1775 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1776 if ( markElem.isNull() )
1779 const QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
1780 return !wellKnownNameElem.isNull();
1786 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1787 if ( graphicElem.isNull() )
1790 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1791 if ( markElem.isNull() )
1795 const QDomElement formatElem = markElem.firstChildElement( QStringLiteral(
"Format" ) );
1796 if ( formatElem.isNull() )
1799 const QString format = formatElem.firstChild().nodeValue();
1800 if ( format != QLatin1String(
"ttf" ) )
1802 QgsDebugError(
"unsupported Graphic Mark format found: " + format );
1807 const QDomElement onlineResourceElem = markElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1808 const QDomElement inlineContentElem = markElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1809 if ( !onlineResourceElem.isNull() )
1812 const QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
1813 if ( !markIndexElem.isNull() )
1816 else if ( !inlineContentElem.isNull() )
1831 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1832 if ( graphicElem.isNull() )
1836 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
1838 if ( it.key() == QLatin1String(
"widthHeightFactor" ) )
1849 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1850 if ( strokeElem.isNull() )
1853 QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral(
"GraphicStroke" ) );
1854 if ( graphicStrokeElem.isNull() )
1862 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1863 if ( fillElem.isNull() )
1866 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1867 if ( graphicFillElem.isNull() )
1870 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1871 if ( graphicElem.isNull() )
1877 QColor fillColor, strokeColor;
1878 double size, strokeWidth;
1879 Qt::PenStyle strokeStyle;
1880 if ( !
wellKnownMarkerFromSld( graphicElem, name, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
1883 if ( name != QLatin1String(
"horline" ) )
1891 const double angle = angleFunc.toDouble( &ok );
1897 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1898 if ( fillElem.isNull() )
1901 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1902 if ( graphicFillElem.isNull() )
1905 const QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1906 if ( graphicElem.isNull() )
1909 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1910 if ( markElem.isNull() )
1918 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1919 if ( fillElem.isNull() )
1922 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1923 if ( graphicFillElem.isNull() )
1931 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1932 if ( fillElem.isNull() )
1935 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1936 if ( graphicFillElem.isNull() )
1956 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1957 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1961 bool validFill =
false, validStroke =
false;
1966 Qt::BrushStyle fillStyle;
1968 if (
fillFromSld( fillElem, fillStyle, fillColor ) )
1974 Qt::PenStyle strokeStyle;
1975 double strokeWidth = 1.0, dashOffset = 0.0;
1976 QVector<qreal> customDashPattern;
1978 if (
lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth,
1979 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
1982 if ( validFill || validStroke )
1985 map[QStringLiteral(
"name" )] = QStringLiteral(
"square" );
1988 map[QStringLiteral(
"size" )] = QString::number( 6 );
1989 map[QStringLiteral(
"angle" )] = QString::number( 0 );
1990 map[QStringLiteral(
"offset" )] =
encodePoint( QPointF( 0, 0 ) );
1997 bool validFill =
false, validStroke =
false;
2000 QString name, format;
2002 QColor fillColor, strokeColor;
2003 double strokeWidth = 1.0, size = 0.0, angle = 0.0;
2007 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
2008 if ( !graphicFillElem.isNull() )
2011 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
2012 if ( !graphicElem.isNull() )
2018 const QDomElement graphicChildElem = graphicElem.firstChildElement();
2019 while ( !graphicChildElem.isNull() )
2021 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2024 const QDomElement wellKnownNameElem = graphicChildElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
2025 if ( !wellKnownNameElem.isNull() )
2027 name = wellKnownNameElem.firstChild().nodeValue();
2033 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) || graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2036 const QDomElement formatElem = graphicChildElem.firstChildElement( QStringLiteral(
"Format" ) );
2037 if ( formatElem.isNull() )
2040 format = formatElem.firstChild().nodeValue();
2044 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) && format != QLatin1String(
"image/svg+xml" ) )
2049 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format != QLatin1String(
"ttf" ) )
2053 const QDomElement onlineResourceElem = graphicChildElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
2054 const QDomElement inlineContentElem = graphicChildElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
2056 if ( !onlineResourceElem.isNull() )
2058 name = onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) );
2060 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format == QLatin1String(
"ttf" ) )
2063 if ( name.startsWith( QLatin1String(
"ttf://" ) ) )
2064 name = name.mid( 6 );
2067 const QDomElement markIndexElem = graphicChildElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
2068 if ( markIndexElem.isNull() )
2072 const int v = markIndexElem.firstChild().nodeValue().toInt( &ok );
2083 else if ( !inlineContentElem.isNull() )
2093 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2095 name = QStringLiteral(
"square" );
2102 if ( found && graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2109 Qt::BrushStyle markFillStyle;
2111 QDomElement markFillElem = graphicChildElem.firstChildElement( QStringLiteral(
"Fill" ) );
2112 if (
fillFromSld( markFillElem, markFillStyle, fillColor ) )
2117 Qt::PenStyle strokeStyle;
2118 double strokeWidth = 1.0, dashOffset = 0.0;
2119 QVector<qreal> customDashPattern;
2121 QDomElement markStrokeElem = graphicChildElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2122 if (
lineFromSld( markStrokeElem, strokeStyle, strokeColor, strokeWidth,
2123 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2130 const QDomElement opacityElem = graphicElem.firstChildElement( QStringLiteral(
"Opacity" ) );
2131 if ( !opacityElem.isNull() )
2132 fillColor.setAlpha(
decodeSldAlpha( opacityElem.firstChild().nodeValue() ) );
2134 const QDomElement sizeElem = graphicElem.firstChildElement( QStringLiteral(
"Size" ) );
2135 if ( !sizeElem.isNull() )
2138 const double v = sizeElem.firstChild().nodeValue().toDouble( &ok );
2147 const double v = angleFunc.toDouble( &ok );
2157 if ( validFill || validStroke )
2159 if ( format == QLatin1String(
"image/svg+xml" ) )
2162 map[QStringLiteral(
"name" )] = name;
2163 map[QStringLiteral(
"fill" )] = fillColor.name();
2164 map[QStringLiteral(
"outline" )] = strokeColor.name();
2165 map[QStringLiteral(
"outline-width" )] = QString::number( strokeWidth );
2167 map[QStringLiteral(
"size" )] = QString::number( size );
2169 map[QStringLiteral(
"angle" )] = QString::number( angle );
2170 if ( !offset.isNull() )
2171 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
2174 else if ( format == QLatin1String(
"ttf" ) )
2177 map[QStringLiteral(
"font" )] = name;
2178 map[QStringLiteral(
"chr" )] = markIndex;
2181 map[QStringLiteral(
"size" )] = QString::number( size );
2183 map[QStringLiteral(
"angle" )] = QString::number( angle );
2184 if ( !offset.isNull() )
2185 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
2191 if ( layers.isEmpty() )
2194 layerList << layers;
2201 QString patternName;
2202 switch ( brushStyle )
2207 case Qt::SolidPattern:
2208 if ( color.isValid() )
2211 if ( color.alpha() < 255 )
2216 case Qt::CrossPattern:
2217 case Qt::DiagCrossPattern:
2218 case Qt::HorPattern:
2219 case Qt::VerPattern:
2220 case Qt::BDiagPattern:
2221 case Qt::FDiagPattern:
2222 case Qt::Dense1Pattern:
2223 case Qt::Dense2Pattern:
2224 case Qt::Dense3Pattern:
2225 case Qt::Dense4Pattern:
2226 case Qt::Dense5Pattern:
2227 case Qt::Dense6Pattern:
2228 case Qt::Dense7Pattern:
2233 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( brushStyle ) ) );
2237 QDomElement graphicFillElem = doc.createElement( QStringLiteral(
"se:GraphicFill" ) );
2238 element.appendChild( graphicFillElem );
2240 QDomElement graphicElem = doc.createElement( QStringLiteral(
"se:Graphic" ) );
2241 graphicFillElem.appendChild( graphicElem );
2243 const QColor fillColor = patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
2244 const QColor strokeColor = !patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
2247 wellKnownMarkerToSld( doc, graphicElem, patternName, fillColor, strokeColor, Qt::SolidLine, -1, -1 );
2254 brushStyle = Qt::SolidPattern;
2255 color = QColor( 128, 128, 128 );
2257 if ( element.isNull() )
2259 brushStyle = Qt::NoBrush;
2264 const QDomElement graphicFillElem = element.firstChildElement( QStringLiteral(
"GraphicFill" ) );
2266 if ( graphicFillElem.isNull() )
2269 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2271 QgsDebugMsgLevel( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ), 2 );
2273 if ( it.key() == QLatin1String(
"fill" ) )
2274 color = QColor( it.value() );
2275 else if ( it.key() == QLatin1String(
"fill-opacity" ) )
2281 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
2282 if ( graphicElem.isNull() )
2285 QString patternName = QStringLiteral(
"square" );
2286 QColor fillColor, strokeColor;
2287 double strokeWidth, size;
2288 Qt::PenStyle strokeStyle;
2289 if ( !
wellKnownMarkerFromSld( graphicElem, patternName, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
2293 if ( brushStyle == Qt::NoBrush )
2296 const QColor
c = patternName.startsWith( QLatin1String(
"brush://" ) ) ? fillColor : strokeColor;
2305 Qt::PenStyle penStyle,
const QColor &color,
double width,
2306 const Qt::PenJoinStyle *penJoinStyle,
const Qt::PenCapStyle *penCapStyle,
2307 const QVector<qreal> *customDashPattern,
double dashOffset )
2309 QVector<qreal> dashPattern;
2310 const QVector<qreal> *pattern = &dashPattern;
2312 if ( penStyle == Qt::CustomDashLine && !customDashPattern )
2314 element.appendChild( doc.createComment( QStringLiteral(
"WARNING: Custom dash pattern required but not provided. Using default dash pattern." ) ) );
2315 penStyle = Qt::DashLine;
2327 dashPattern.push_back( 4.0 );
2328 dashPattern.push_back( 2.0 );
2331 dashPattern.push_back( 1.0 );
2332 dashPattern.push_back( 2.0 );
2334 case Qt::DashDotLine:
2335 dashPattern.push_back( 4.0 );
2336 dashPattern.push_back( 2.0 );
2337 dashPattern.push_back( 1.0 );
2338 dashPattern.push_back( 2.0 );
2340 case Qt::DashDotDotLine:
2341 dashPattern.push_back( 4.0 );
2342 dashPattern.push_back( 2.0 );
2343 dashPattern.push_back( 1.0 );
2344 dashPattern.push_back( 2.0 );
2345 dashPattern.push_back( 1.0 );
2346 dashPattern.push_back( 2.0 );
2349 case Qt::CustomDashLine:
2350 Q_ASSERT( customDashPattern );
2351 pattern = customDashPattern;
2355 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( penStyle ) ) );
2359 if ( color.isValid() )
2362 if ( color.alpha() < 255 )
2369 else if ( width == 0 )
2379 if ( !pattern->isEmpty() )
2389 Qt::PenStyle &penStyle, QColor &color,
double &width,
2390 Qt::PenJoinStyle *penJoinStyle, Qt::PenCapStyle *penCapStyle,
2391 QVector<qreal> *customDashPattern,
double *dashOffset )
2395 penStyle = Qt::SolidLine;
2396 color = QColor( 0, 0, 0 );
2399 *penJoinStyle = Qt::BevelJoin;
2401 *penCapStyle = Qt::SquareCap;
2402 if ( customDashPattern )
2403 customDashPattern->clear();
2407 if ( element.isNull() )
2409 penStyle = Qt::NoPen;
2415 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2417 QgsDebugMsgLevel( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ), 2 );
2419 if ( it.key() == QLatin1String(
"stroke" ) )
2421 color = QColor( it.value() );
2423 else if ( it.key() == QLatin1String(
"stroke-opacity" ) )
2427 else if ( it.key() == QLatin1String(
"stroke-width" ) )
2430 const double w = it.value().toDouble( &ok );
2434 else if ( it.key() == QLatin1String(
"stroke-linejoin" ) && penJoinStyle )
2438 else if ( it.key() == QLatin1String(
"stroke-linecap" ) && penCapStyle )
2442 else if ( it.key() == QLatin1String(
"stroke-dasharray" ) )
2445 if ( !dashPattern.isEmpty() )
2449 bool dashPatternFound =
false;
2451 if ( dashPattern.count() == 2 )
2453 if ( dashPattern.at( 0 ) == 4.0 &&
2454 dashPattern.at( 1 ) == 2.0 )
2456 penStyle = Qt::DashLine;
2457 dashPatternFound =
true;
2459 else if ( dashPattern.at( 0 ) == 1.0 &&
2460 dashPattern.at( 1 ) == 2.0 )
2462 penStyle = Qt::DotLine;
2463 dashPatternFound =
true;
2466 else if ( dashPattern.count() == 4 )
2468 if ( dashPattern.at( 0 ) == 4.0 &&
2469 dashPattern.at( 1 ) == 2.0 &&
2470 dashPattern.at( 2 ) == 1.0 &&
2471 dashPattern.at( 3 ) == 2.0 )
2473 penStyle = Qt::DashDotLine;
2474 dashPatternFound =
true;
2477 else if ( dashPattern.count() == 6 )
2479 if ( dashPattern.at( 0 ) == 4.0 &&
2480 dashPattern.at( 1 ) == 2.0 &&
2481 dashPattern.at( 2 ) == 1.0 &&
2482 dashPattern.at( 3 ) == 2.0 &&
2483 dashPattern.at( 4 ) == 1.0 &&
2484 dashPattern.at( 5 ) == 2.0 )
2486 penStyle = Qt::DashDotDotLine;
2487 dashPatternFound =
true;
2492 if ( !dashPatternFound )
2494 if ( customDashPattern )
2496 penStyle = Qt::CustomDashLine;
2497 *customDashPattern = dashPattern;
2501 QgsDebugMsgLevel( QStringLiteral(
"custom dash pattern required but not provided. Using default dash pattern." ), 2 );
2502 penStyle = Qt::DashLine;
2507 else if ( it.key() == QLatin1String(
"stroke-dashoffset" ) && dashOffset )
2510 const double d = it.value().toDouble( &ok );
2520 const QString &path,
const QString &mime,
2521 const QColor &color,
double size )
2523 QDomElement externalGraphicElem = doc.createElement( QStringLiteral(
"se:ExternalGraphic" ) );
2524 element.appendChild( externalGraphicElem );
2533 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2535 element.appendChild( sizeElem );
2540 const QString &path,
const QColor &fillColor,
double size,
const QColor &strokeColor,
double strokeWidth )
2547 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Parametric SVG" ) ) );
2548 const QString parametricPath =
getSvgParametricPath( path, fillColor, strokeColor, strokeWidth );
2551 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Plain SVG fallback, no parameters" ) ) );
2554 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Well known marker fallback" ) ) );
2560 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2562 graphicElem.appendChild( sizeElem );
2570 if ( fillColor.isValid() )
2572 url.addQueryItem( QStringLiteral(
"fill" ), fillColor.name() );
2573 url.addQueryItem( QStringLiteral(
"fill-opacity" ),
encodeSldAlpha( fillColor.alpha() ) );
2577 url.addQueryItem( QStringLiteral(
"fill" ), QStringLiteral(
"#000000" ) );
2578 url.addQueryItem( QStringLiteral(
"fill-opacity" ), QStringLiteral(
"1" ) );
2580 if ( strokeColor.isValid() )
2582 url.addQueryItem( QStringLiteral(
"outline" ), strokeColor.name() );
2583 url.addQueryItem( QStringLiteral(
"outline-opacity" ),
encodeSldAlpha( strokeColor.alpha() ) );
2587 url.addQueryItem( QStringLiteral(
"outline" ), QStringLiteral(
"#000000" ) );
2588 url.addQueryItem( QStringLiteral(
"outline-opacity" ), QStringLiteral(
"1" ) );
2590 url.addQueryItem( QStringLiteral(
"outline-width" ), QString::number( strokeWidth ) );
2591 const QString params = url.toString( QUrl::FullyEncoded );
2592 if ( params.isEmpty() )
2598 return basePath +
"?" + params;
2603 QString &path, QString &mime,
2604 QColor &color,
double &size )
2609 QDomElement externalGraphicElem = element.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
2610 if ( externalGraphicElem.isNull() )
2615 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2616 if ( !sizeElem.isNull() )
2619 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2628 const QString &path,
const QString &format,
int *markIndex,
2629 const QColor &color,
double size )
2631 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2632 element.appendChild( markElem );
2638 QDomElement markIndexElem = doc.createElement( QStringLiteral(
"se:MarkIndex" ) );
2639 markIndexElem.appendChild( doc.createTextNode( QString::number( *markIndex ) ) );
2640 markElem.appendChild( markIndexElem );
2644 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2645 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2646 markElem.appendChild( fillElem );
2651 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2653 element.appendChild( sizeElem );
2658 QString &path, QString &format,
int &markIndex,
2659 QColor &color,
double &size )
2667 QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2668 if ( markElem.isNull() )
2673 const QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
2674 if ( !markIndexElem.isNull() )
2677 const int i = markIndexElem.firstChild().nodeValue().toInt( &ok );
2683 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2684 Qt::BrushStyle b = Qt::SolidPattern;
2689 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2690 if ( !sizeElem.isNull() )
2693 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2702 const QString &name,
const QColor &color,
const QColor &strokeColor, Qt::PenStyle strokeStyle,
2703 double strokeWidth,
double size )
2705 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2706 element.appendChild( markElem );
2708 QDomElement wellKnownNameElem = doc.createElement( QStringLiteral(
"se:WellKnownName" ) );
2709 wellKnownNameElem.appendChild( doc.createTextNode( name ) );
2710 markElem.appendChild( wellKnownNameElem );
2713 if ( color.isValid() )
2715 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2716 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2717 markElem.appendChild( fillElem );
2721 if ( strokeColor.isValid() )
2723 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
2724 lineToSld( doc, strokeElem, strokeStyle, strokeColor, strokeWidth );
2725 markElem.appendChild( strokeElem );
2731 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2733 element.appendChild( sizeElem );
2738 QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle,
2739 double &strokeWidth,
double &size )
2743 name = QStringLiteral(
"square" );
2745 strokeColor = QColor( 0, 0, 0 );
2749 const QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2750 if ( markElem.isNull() )
2753 const QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
2754 if ( !wellKnownNameElem.isNull() )
2756 name = wellKnownNameElem.firstChild().nodeValue();
2761 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2762 Qt::BrushStyle b = Qt::SolidPattern;
2767 QDomElement strokeElem = markElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2768 lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth );
2772 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2773 if ( !sizeElem.isNull() )
2776 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2786 if ( !rotationFunc.isEmpty() )
2788 QDomElement rotationElem = doc.createElement( QStringLiteral(
"se:Rotation" ) );
2790 element.appendChild( rotationElem );
2796 QDomElement rotationElem = element.firstChildElement( QStringLiteral(
"Rotation" ) );
2797 if ( !rotationElem.isNull() )
2807 if ( !alphaFunc.isEmpty() )
2809 QDomElement opacityElem = doc.createElement( QStringLiteral(
"se:Opacity" ) );
2811 element.appendChild( opacityElem );
2817 QDomElement opacityElem = element.firstChildElement( QStringLiteral(
"Opacity" ) );
2818 if ( !opacityElem.isNull() )
2827 if ( offset.isNull() )
2830 QDomElement displacementElem = doc.createElement( QStringLiteral(
"se:Displacement" ) );
2831 element.appendChild( displacementElem );
2833 QDomElement dispXElem = doc.createElement( QStringLiteral(
"se:DisplacementX" ) );
2834 dispXElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.x(), 2 ) ) );
2836 QDomElement dispYElem = doc.createElement( QStringLiteral(
"se:DisplacementY" ) );
2837 dispYElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.y(), 2 ) ) );
2839 displacementElem.appendChild( dispXElem );
2840 displacementElem.appendChild( dispYElem );
2847 QDomElement anchorElem = doc.createElement( QStringLiteral(
"se:AnchorPoint" ) );
2848 element.appendChild( anchorElem );
2850 QDomElement anchorXElem = doc.createElement( QStringLiteral(
"se:AnchorPointX" ) );
2851 anchorXElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.x() ) ) );
2853 QDomElement anchorYElem = doc.createElement( QStringLiteral(
"se:AnchorPointY" ) );
2854 anchorYElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.y() ) ) );
2856 anchorElem.appendChild( anchorXElem );
2857 anchorElem.appendChild( anchorYElem );
2862 offset = QPointF( 0, 0 );
2864 const QDomElement displacementElem = element.firstChildElement( QStringLiteral(
"Displacement" ) );
2865 if ( displacementElem.isNull() )
2868 const QDomElement dispXElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementX" ) );
2869 if ( !dispXElem.isNull() )
2872 const double offsetX = dispXElem.firstChild().nodeValue().toDouble( &ok );
2874 offset.setX( offsetX );
2877 const QDomElement dispYElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementY" ) );
2878 if ( !dispYElem.isNull() )
2881 const double offsetY = dispYElem.firstChild().nodeValue().toDouble( &ok );
2883 offset.setY( offsetY );
2890 const QString &label,
const QFont &font,
2891 const QColor &color,
double size )
2893 QDomElement labelElem = doc.createElement( QStringLiteral(
"se:Label" ) );
2894 labelElem.appendChild( doc.createTextNode( label ) );
2895 element.appendChild( labelElem );
2897 QDomElement fontElem = doc.createElement( QStringLiteral(
"se:Font" ) );
2898 element.appendChild( fontElem );
2902 fontElem.appendChild( createSldParameterElement( doc,
"font-style",
encodeSldFontStyle( font.style() ) ) );
2903 fontElem.appendChild( createSldParameterElement( doc,
"font-weight",
encodeSldFontWeight( font.weight() ) ) );
2908 if ( color.isValid() )
2910 QDomElement fillElem = doc.createElement( QStringLiteral(
"Fill" ) );
2911 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2912 element.appendChild( fillElem );
2917 Qt::PenJoinStyle joinStyle,
2918 Qt::PenCapStyle capStyle,
2920 const QVector<qreal> *dashPattern )
2923 penStyle.append(
"PEN(" );
2924 penStyle.append(
"c:" );
2925 penStyle.append(
c.name() );
2926 penStyle.append(
",w:" );
2928 penStyle.append( QString::number( width * mmScaleFactor ) );
2929 penStyle.append(
"mm" );
2932 if ( dashPattern && !dashPattern->isEmpty() )
2934 penStyle.append(
",p:\"" );
2935 QVector<qreal>::const_iterator pIt = dashPattern->constBegin();
2936 for ( ; pIt != dashPattern->constEnd(); ++pIt )
2938 if ( pIt != dashPattern->constBegin() )
2940 penStyle.append(
' ' );
2942 penStyle.append( QString::number( *pIt * mapUnitScaleFactor ) );
2943 penStyle.append(
'g' );
2945 penStyle.append(
'\"' );
2949 penStyle.append(
",cap:" );
2953 penStyle.append(
'p' );
2956 penStyle.append(
'r' );
2960 penStyle.append(
'b' );
2964 penStyle.append(
",j:" );
2965 switch ( joinStyle )
2968 penStyle.append(
'b' );
2971 penStyle.append(
'r' );
2975 penStyle.append(
'm' );
2981 penStyle.append(
",dp:" );
2982 penStyle.append( QString::number( offset * mapUnitScaleFactor ) );
2983 penStyle.append(
'g' );
2986 penStyle.append(
')' );
2993 brushStyle.append(
"BRUSH(" );
2994 brushStyle.append(
"fc:" );
2995 brushStyle.append( fillColor.name() );
2996 brushStyle.append(
')' );
3002 if ( geomFunc.isEmpty() )
3005 QDomElement geometryElem = doc.createElement( QStringLiteral(
"Geometry" ) );
3006 element.appendChild( geometryElem );
3036 QDomElement geometryElem = element.firstChildElement( QStringLiteral(
"Geometry" ) );
3037 if ( geometryElem.isNull() )
3049 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " + function ) );
3053 if ( !filterElem.isNull() )
3054 element.appendChild( filterElem );
3062 if ( function == QLatin1String(
"ELSE" ) )
3065 element.appendChild( filterElem );
3074 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " + function ) );
3078 if ( !filterElem.isNull() )
3079 element.appendChild( filterElem );
3087 QDomElement elem = element;
3088 if ( element.tagName() != QLatin1String(
"Filter" ) )
3090 const QDomNodeList filterNodes = element.elementsByTagName( QStringLiteral(
"Filter" ) );
3091 if ( !filterNodes.isEmpty() )
3093 elem = filterNodes.at( 0 ).toElement();
3097 if ( elem.isNull() )
3122 const QString &path,
const QString &format )
3126 QDomElement onlineResourceElem = doc.createElement( QStringLiteral(
"se:OnlineResource" ) );
3127 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
3128 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:href" ), url );
3129 element.appendChild( onlineResourceElem );
3131 QDomElement formatElem = doc.createElement( QStringLiteral(
"se:Format" ) );
3132 formatElem.appendChild( doc.createTextNode( format ) );
3133 element.appendChild( formatElem );
3140 const QDomElement onlineResourceElem = element.firstChildElement( QStringLiteral(
"OnlineResource" ) );
3141 if ( onlineResourceElem.isNull() )
3144 path = QUrl::fromPercentEncoding( onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) ).toUtf8() );
3146 const QDomElement formatElem = element.firstChildElement( QStringLiteral(
"Format" ) );
3147 if ( formatElem.isNull() )
3150 format = formatElem.firstChild().nodeValue();
3157 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:SvgParameter" ) );
3158 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
3159 nodeElem.appendChild( doc.createTextNode( value ) );
3168 QDomElement paramElem = element.firstChildElement();
3169 while ( !paramElem.isNull() )
3171 if ( paramElem.localName() == QLatin1String(
"SvgParameter" ) || paramElem.localName() == QLatin1String(
"CssParameter" ) )
3173 const QString name = paramElem.attribute( QStringLiteral(
"name" ) );
3174 if ( paramElem.firstChild().nodeType() == QDomNode::TextNode )
3176 value = paramElem.firstChild().nodeValue();
3180 if ( paramElem.firstChild().nodeType() == QDomNode::ElementNode &&
3181 paramElem.firstChild().localName() == QLatin1String(
"Literal" ) )
3184 value = paramElem.firstChild().firstChild().nodeValue();
3188 QgsDebugError( QStringLiteral(
"unexpected child of %1" ).arg( paramElem.localName() ) );
3192 if ( !name.isEmpty() && !value.isEmpty() )
3193 params[ name ] = value;
3196 paramElem = paramElem.nextSiblingElement();
3204 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:VendorOption" ) );
3205 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
3206 nodeElem.appendChild( doc.createTextNode( value ) );
3214 QDomElement paramElem = element.firstChildElement( QStringLiteral(
"VendorOption" ) );
3215 while ( !paramElem.isNull() )
3217 const QString name = paramElem.attribute( QStringLiteral(
"name" ) );
3218 const QString value = paramElem.firstChild().nodeValue();
3220 if ( !name.isEmpty() && !value.isEmpty() )
3221 params[ name ] = value;
3223 paramElem = paramElem.nextSiblingElement( QStringLiteral(
"VendorOption" ) );
3233 if ( newSymbols.userType() == QMetaType::Type::QVariantMap )
3235 return newSymbols.toMap();
3242 QDomElement e = element.firstChildElement();
3243 while ( !e.isNull() )
3245 if ( e.tagName() == QLatin1String(
"prop" ) )
3247 const QString propKey = e.attribute( QStringLiteral(
"k" ) );
3248 const QString propValue = e.attribute( QStringLiteral(
"v" ) );
3249 props[propKey] = propValue;
3251 e = e.nextSiblingElement();
3268 QDomElement e = element.firstChildElement();
3270 while ( !e.isNull() )
3272 if ( e.tagName() == QLatin1String(
"symbol" ) )
3276 symbols.insert( e.attribute( QStringLiteral(
"name" ) ), symbol );
3282 e = e.nextSiblingElement();
3289 QStringList subsymbols;
3291 for ( QMap<QString, QgsSymbol *>::iterator it = symbols.begin(); it != symbols.end(); ++it )
3293 if ( it.key()[0] !=
'@' )
3297 subsymbols.append( it.key() );
3299 QStringList parts = it.key().split(
'@' );
3300 if ( parts.count() < 3 )
3302 QgsDebugError(
"found subsymbol with invalid name: " + it.key() );
3306 const QString symname = parts[1];
3307 const int symlayer = parts[2].toInt();
3309 if ( !symbols.contains( symname ) )
3311 QgsDebugError(
"subsymbol references invalid symbol: " + symname );
3319 QgsDebugError(
"subsymbol references invalid symbol layer: " + QString::number( symlayer ) );
3328 QgsDebugError(
"symbol layer refused subsymbol: " + it.key() );
3335 for (
int i = 0; i < subsymbols.count(); i++ )
3336 symbols.take( subsymbols[i] );
3343 QDomElement symbolsElem = doc.createElement( tagName );
3346 for ( QMap<QString, QgsSymbol *>::iterator its = symbols.begin(); its != symbols.end(); ++its )
3348 const QDomElement symEl =
saveSymbol( its.key(), its.value(), doc, context );
3349 symbolsElem.appendChild( symEl );
3357 qDeleteAll( symbols );
3366 std::unique_ptr< QMimeData >mimeData(
new QMimeData );
3368 QDomDocument symbolDoc;
3370 symbolDoc.appendChild( symbolElem );
3371 mimeData->setText( symbolDoc.toString() );
3374 mimeData->setColorData( symbol->
color() );
3376 return mimeData.release();
3384 const QString text = data->text();
3385 if ( !text.isEmpty() )
3390 if ( doc.setContent( text ) )
3392 elem = doc.documentElement();
3394 if ( elem.nodeName() != QLatin1String(
"symbol" ) )
3395 elem = elem.firstChildElement( QStringLiteral(
"symbol" ) );
3406 const QString rampType = element.attribute( QStringLiteral(
"type" ) );
3431 QDomElement rampEl = doc.createElement( QStringLiteral(
"colorramp" ) );
3432 rampEl.setAttribute( QStringLiteral(
"type" ), ramp->
type() );
3433 rampEl.setAttribute( QStringLiteral(
"name" ), name );
3441 QVariantMap rampMap;
3443 rampMap.insert( QStringLiteral(
"type" ), ramp->
type() );
3444 rampMap.insert( QStringLiteral(
"name" ), name );
3446 const QVariantMap properties = ramp->
properties();
3448 QVariantMap propertyMap;
3449 for (
auto property = properties.constBegin();
property != properties.constEnd(); ++property )
3451 propertyMap.insert( property.key(),
property.value() );
3454 rampMap.insert( QStringLiteral(
"properties" ), propertyMap );
3460 const QVariantMap rampMap = value.toMap();
3462 const QString rampType = rampMap.
value( QStringLiteral(
"type" ) ).toString();
3465 const QVariantMap propertyMap = rampMap.value( QStringLiteral(
"properties" ) ).toMap();
3468 for (
auto property = propertyMap.constBegin();
property != propertyMap.constEnd(); ++property )
3470 props.insert( property.key(),
property.value().toString() );
3492 if ( !color.isValid() )
3499 return color.name();
3504 QList<QColor> colors;
3507 const thread_local QRegularExpression sepCommaSpaceRegExp(
"(,|\\s)" );
3508 QStringList components = colorStr.simplified().split( sepCommaSpaceRegExp );
3509 QStringList::iterator it = components.begin();
3510 for ( ; it != components.end(); ++it )
3512 const QColor result =
parseColor( *it,
true );
3513 if ( result.isValid() )
3518 if ( colors.length() > 0 )
3524 const thread_local QRegularExpression sepCommaRegExp(
"(,|\n)" );
3525 components = colorStr.split( sepCommaRegExp );
3526 it = components.begin();
3527 for ( ; it != components.end(); ++it )
3529 const QColor result =
parseColor( *it,
true );
3530 if ( result.isValid() )
3535 if ( colors.length() > 0 )
3541 components = colorStr.simplified().split( QString(
' ' ) );
3542 it = components.begin();
3543 for ( ; it != components.end(); ++it )
3545 const QColor result =
parseColor( *it,
true );
3546 if ( result.isValid() )
3551 if ( colors.length() > 0 )
3557 components = colorStr.split(
'\n' );
3558 it = components.begin();
3559 for ( ; it != components.end(); ++it )
3561 const QColor result =
parseColor( *it,
true );
3562 if ( result.isValid() )
3575 QMimeData *mimeData =
new QMimeData;
3576 mimeData->setColorData( QVariant( color ) );
3577 mimeData->setText( color.name() );
3584 if ( mimeData->hasColor() )
3586 QColor mimeColor = mimeData->colorData().value<QColor>();
3587 if ( mimeColor.isValid() )
3595 if ( mimeData->hasText() )
3599 if ( textColor.isValid() )
3614 if ( data->hasFormat( QStringLiteral(
"text/xml" ) ) )
3617 const QByteArray encodedData = data->data( QStringLiteral(
"text/xml" ) );
3618 QDomDocument xmlDoc;
3619 xmlDoc.setContent( encodedData );
3621 const QDomElement dragDataElem = xmlDoc.documentElement();
3622 if ( dragDataElem.tagName() == QLatin1String(
"ColorSchemeModelDragData" ) )
3624 const QDomNodeList nodeList = dragDataElem.childNodes();
3625 const int nChildNodes = nodeList.size();
3626 QDomElement currentElem;
3628 for (
int i = 0; i < nChildNodes; ++i )
3630 currentElem = nodeList.at( i ).toElement();
3631 if ( currentElem.isNull() )
3636 QPair< QColor, QString> namedColor;
3638 namedColor.second = currentElem.attribute( QStringLiteral(
"label" ), QString() );
3640 mimeColors << namedColor;
3645 if ( mimeColors.length() == 0 && data->hasFormat( QStringLiteral(
"application/x-colorobject-list" ) ) )
3648 const QByteArray encodedData = data->data( QStringLiteral(
"application/x-colorobject-list" ) );
3649 QDomDocument xmlDoc;
3650 xmlDoc.setContent( encodedData );
3652 const QDomNodeList colorsNodes = xmlDoc.elementsByTagName( QStringLiteral(
"colors" ) );
3653 if ( colorsNodes.length() > 0 )
3655 const QDomElement colorsElem = colorsNodes.at( 0 ).toElement();
3656 const QDomNodeList colorNodeList = colorsElem.childNodes();
3657 const int nChildNodes = colorNodeList.size();
3658 QDomElement currentElem;
3660 for (
int i = 0; i < nChildNodes; ++i )
3663 currentElem = colorNodeList.at( i ).toElement();
3664 if ( currentElem.isNull() )
3669 const QDomNodeList colorNodes = currentElem.elementsByTagName( QStringLiteral(
"color" ) );
3670 const QDomNodeList nameNodes = currentElem.elementsByTagName( QStringLiteral(
"name" ) );
3672 if ( colorNodes.length() > 0 )
3674 const QDomElement colorElem = colorNodes.at( 0 ).toElement();
3676 const QStringList colorParts = colorElem.text().simplified().split(
' ' );
3677 if ( colorParts.length() < 3 )
3682 const int red = colorParts.at( 0 ).toDouble() * 255;
3683 const int green = colorParts.at( 1 ).toDouble() * 255;
3684 const int blue = colorParts.at( 2 ).toDouble() * 255;
3685 QPair< QColor, QString> namedColor;
3686 namedColor.first = QColor( red, green, blue );
3687 if ( nameNodes.length() > 0 )
3689 const QDomElement nameElem = nameNodes.at( 0 ).toElement();
3690 namedColor.second = nameElem.text();
3692 mimeColors << namedColor;
3698 if ( mimeColors.length() == 0 && data->hasText() )
3702 QList< QColor >::iterator it = parsedColors.begin();
3703 for ( ; it != parsedColors.end(); ++it )
3705 mimeColors << qMakePair( *it, QString() );
3709 if ( mimeColors.length() == 0 && data->hasColor() )
3712 const QColor mimeColor = data->colorData().value<QColor>();
3713 if ( mimeColor.isValid() )
3715 mimeColors << qMakePair( mimeColor, QString() );
3725 QMimeData *mimeData =
new QMimeData();
3726 QDomDocument xmlDoc;
3727 QDomElement xmlRootElement = xmlDoc.createElement( QStringLiteral(
"ColorSchemeModelDragData" ) );
3728 xmlDoc.appendChild( xmlRootElement );
3730 QgsNamedColorList::const_iterator colorIt = colorList.constBegin();
3731 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3733 QDomElement namedColor = xmlDoc.createElement( QStringLiteral(
"NamedColor" ) );
3735 namedColor.setAttribute( QStringLiteral(
"label" ), ( *colorIt ).second );
3736 xmlRootElement.appendChild( namedColor );
3738 mimeData->setData( QStringLiteral(
"text/xml" ), xmlDoc.toByteArray() );
3746 colorIt = colorList.constBegin();
3747 QStringList colorListString;
3748 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3750 colorListString << ( *colorIt ).first.name();
3752 mimeData->setText( colorListString.join( QLatin1Char(
'\n' ) ) );
3755 if ( colorList.length() > 0 )
3757 mimeData->setColorData( QVariant( colorList.at( 0 ).first ) );
3765 if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3770 QTextStream stream( &file );
3771 stream <<
"GIMP Palette" << Qt::endl;
3772 if ( paletteName.isEmpty() )
3774 stream <<
"Name: QGIS Palette" << Qt::endl;
3778 stream <<
"Name: " << paletteName << Qt::endl;
3780 stream <<
"Columns: 4" << Qt::endl;
3781 stream <<
'#' << Qt::endl;
3783 for ( QgsNamedColorList::ConstIterator colorIt = colors.constBegin(); colorIt != colors.constEnd(); ++colorIt )
3785 const QColor color = ( *colorIt ).first;
3786 if ( !color.isValid() )
3790 stream << QStringLiteral(
"%1 %2 %3" ).arg( color.red(), 3 ).arg( color.green(), 3 ).arg( color.blue(), 3 );
3791 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << Qt::endl;
3802 if ( !file.open( QIODevice::ReadOnly ) )
3805 return importedColors;
3808 QTextStream in( &file );
3810 QString line = in.readLine();
3811 if ( !line.startsWith( QLatin1String(
"GIMP Palette" ) ) )
3814 return importedColors;
3818 while ( !in.atEnd() && !line.startsWith( QLatin1String(
"Name:" ) ) && !line.startsWith(
'#' ) )
3820 line = in.readLine();
3822 if ( line.startsWith( QLatin1String(
"Name:" ) ) )
3824 const thread_local QRegularExpression nameRx(
"Name:\\s*(\\S.*)$" );
3825 const QRegularExpressionMatch match = nameRx.match( line );
3826 if ( match.hasMatch() )
3828 name = match.captured( 1 );
3833 while ( !in.atEnd() && !line.startsWith(
'#' ) )
3835 line = in.readLine();
3840 return importedColors;
3844 const thread_local QRegularExpression rx(
"^\\s*(\\d+)\\s+(\\d+)\\s+(\\d+)(\\s.*)?$" );
3845 while ( !in.atEnd() )
3847 line = in.readLine();
3848 const QRegularExpressionMatch match = rx.match( line );
3849 if ( !match.hasMatch() )
3853 const int red = match.captured( 1 ).toInt();
3854 const int green = match.captured( 2 ).toInt();
3855 const int blue = match.captured( 3 ).toInt();
3856 const QColor color = QColor( red, green, blue );
3857 if ( !color.isValid() )
3864 if ( rx.captureCount() > 3 )
3866 label = match.captured( 4 ).simplified();
3873 importedColors << qMakePair( color, label );
3878 return importedColors;
3891 const thread_local QRegularExpression hexColorAlphaRx(
"^\\s*#?([0-9a-fA-F]{6})([0-9a-fA-F]{2})\\s*$" );
3892 QRegularExpressionMatch match = hexColorAlphaRx.match( colorStr );
3895 if ( !match.hasMatch() && QColor::isValidColor( colorStr ) )
3898 parsedColor.setNamedColor( colorStr );
3899 if ( parsedColor.isValid() )
3901 containsAlpha =
false;
3907 if ( match.hasMatch() )
3909 const QString hexColor = match.captured( 1 );
3910 parsedColor.setNamedColor( QStringLiteral(
"#" ) + hexColor );
3912 const int alphaHex = match.captured( 2 ).toInt( &alphaOk, 16 );
3914 if ( parsedColor.isValid() && alphaOk )
3916 parsedColor.setAlpha( alphaHex );
3917 containsAlpha =
true;
3925 const thread_local QRegularExpression hexColorRx2(
"^\\s*(?:[0-9a-fA-F]{3}){1,2}\\s*$" );
3926 if ( colorStr.indexOf( hexColorRx2 ) != -1 )
3929 parsedColor.setNamedColor( QStringLiteral(
"#" ) + colorStr );
3930 if ( parsedColor.isValid() )
3932 containsAlpha =
false;
3939 const thread_local QRegularExpression rgbFormatRx(
"^\\s*(?:rgb)?\\(?\\s*((?:[01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])(?:\\.\\d*)?)\\s*,\\s*((?:[01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])(?:\\.\\d*)?)\\s*,\\s*((?:[01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])(?:\\.\\d*)?)\\s*\\)?\\s*;?\\s*$" );
3940 match = rgbFormatRx.match( colorStr );
3941 if ( match.hasMatch() )
3946 const int r = match.captured( 1 ).toInt( &rOk );
3947 const int g = match.captured( 2 ).toInt( &gOk );
3948 const int b = match.captured( 3 ).toInt( &bOk );
3950 if ( !rOk || !gOk || !bOk )
3952 const float rFloat = match.captured( 1 ).toFloat();
3953 const float gFloat = match.captured( 2 ).toFloat();
3954 const float bFloat = match.captured( 3 ).toFloat();
3955 parsedColor.setRgbF( rFloat / 255.0, gFloat / 255.0, bFloat / 255.0 );
3959 parsedColor.setRgb( r, g, b );
3962 if ( parsedColor.isValid() )
3964 containsAlpha =
false;
3970 const thread_local QRegularExpression hslFormatRx(
"^\\s*hsl\\(?\\s*(\\d+(?:\\.\\d*)?)\\s*,\\s*(\\d+(?:\\.\\d*)?)\\s*%\\s*,\\s*(\\d+(?:\\.\\d*)?)\\s*%\\s*\\)?\\s*;?\\s*$" );
3971 match = hslFormatRx.match( colorStr );
3972 if ( match.hasMatch() )
3977 const int h = match.captured( 1 ).toInt( &hOk );
3978 const int s = match.captured( 2 ).toInt( &sOk );
3979 const int l = match.captured( 3 ).toInt( &lOk );
3981 if ( !hOk || !sOk || !lOk )
3983 const float hFloat = match.captured( 1 ).toFloat();
3984 const float sFloat = match.captured( 2 ).toFloat();
3985 const float lFloat = match.captured( 3 ).toFloat();
3986 parsedColor.setHslF( hFloat / 360.0, sFloat / 100.0, lFloat / 100.0 );
3990 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0 );
3992 if ( parsedColor.isValid() )
3994 containsAlpha =
false;
4000 const thread_local QRegularExpression rgbPercentFormatRx(
"^\\s*(?:rgb)?\\(?\\s*(100|0*\\d{1,2}(?:\\.\\d*)?)\\s*%\\s*,\\s*(100|0*\\d{1,2}(?:\\.\\d*)?)\\s*%\\s*,\\s*(100|0*\\d{1,2}(?:\\.\\d*)?)\\s*%\\s*\\)?\\s*;?\\s*$" );
4001 match = rgbPercentFormatRx.match( colorStr );
4002 if ( match.hasMatch() )
4004 const double r = match.captured( 1 ).toDouble() / 100;
4005 const double g = match.captured( 2 ).toDouble() / 100;
4006 const double b = match.captured( 3 ).toDouble() / 100;
4007 parsedColor.setRgbF( r, g, b );
4008 if ( parsedColor.isValid() )
4010 containsAlpha =
false;
4016 const thread_local QRegularExpression rgbaFormatRx(
"^\\s*(?:rgba)?\\(?\\s*((?:[01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])(?:\\.\\d*)?)\\s*,\\s*((?:[01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])(?:\\.\\d*)?)\\s*,\\s*((?:[01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])(?:\\.\\d*)?)\\s*,\\s*(0|0?\\.\\d*|1(?:\\.0*)?)\\s*\\)?\\s*;?\\s*$" );
4017 match = rgbaFormatRx.match( colorStr );
4018 if ( match.hasMatch() )
4023 const int r = match.captured( 1 ).toInt( &rOk );
4024 const int g = match.captured( 2 ).toInt( &gOk );
4025 const int b = match.captured( 3 ).toInt( &bOk );
4026 const double aDouble = match.captured( 4 ).toDouble();
4028 if ( !rOk || !gOk || !bOk )
4030 const float rFloat = match.captured( 1 ).toFloat();
4031 const float gFloat = match.captured( 2 ).toFloat();
4032 const float bFloat = match.captured( 3 ).toFloat();
4033 parsedColor.setRgbF( rFloat / 255.0, gFloat / 255.0, bFloat / 255.0, aDouble );
4037 const int a =
static_cast< int >( std::round( match.captured( 4 ).toDouble() * 255.0 ) );
4038 parsedColor.setRgb( r, g, b, a );
4040 if ( parsedColor.isValid() )
4042 containsAlpha =
true;
4048 const thread_local QRegularExpression rgbaPercentFormatRx(
"^\\s*(?:rgba)?\\(?\\s*(100|0*\\d{1,2}(?:\\.\\d*)?)\\s*%\\s*,\\s*(100|0*\\d{1,2}(?:\\.\\d*)?)\\s*%\\s*,\\s*(100|0*\\d{1,2}(?:\\.\\d*)?)\\s*%\\s*,\\s*(0|0?\\.\\d*|1(?:\\.0*)?)\\s*\\)?\\s*;?\\s*$" );
4049 match = rgbaPercentFormatRx.match( colorStr );
4050 if ( match.hasMatch() )
4052 const double r = match.captured( 1 ).toDouble() / 100;
4053 const double g = match.captured( 2 ).toDouble() / 100;
4054 const double b = match.captured( 3 ).toDouble() / 100;
4055 const double a = match.captured( 4 ).toDouble();
4056 parsedColor.setRgbF( r, g, b, a );
4057 if ( parsedColor.isValid() )
4059 containsAlpha =
true;
4065 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*$" );
4066 match = hslaPercentFormatRx.match( colorStr );
4067 if ( match.hasMatch() )
4072 const int h = match.captured( 1 ).toInt( &hOk );
4073 const int s = match.captured( 2 ).toInt( &sOk );
4074 const int l = match.captured( 3 ).toInt( &lOk );
4075 const double aDouble = match.captured( 4 ).toDouble();
4077 if ( !hOk || !sOk || !lOk )
4079 const float hFloat = match.captured( 1 ).toFloat();
4080 const float sFloat = match.captured( 2 ).toFloat();
4081 const float lFloat = match.captured( 3 ).toFloat();
4082 parsedColor.setHslF( hFloat / 360.0, sFloat / 100.0, lFloat / 100.0, aDouble );
4086 const int a = std::round( aDouble * 255.0 );
4087 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0, a );
4090 if ( parsedColor.isValid() )
4092 containsAlpha =
true;
4109 const QImage::Format format = image->format();
4110 if ( format != QImage::Format_ARGB32_Premultiplied && format != QImage::Format_ARGB32 )
4117 for (
int heightIndex = 0; heightIndex < image->height(); ++heightIndex )
4119 QRgb *scanLine =
reinterpret_cast< QRgb *
>( image->scanLine( heightIndex ) );
4120 for (
int widthIndex = 0; widthIndex < image->width(); ++widthIndex )
4122 myRgb = scanLine[widthIndex];
4123 if ( format == QImage::Format_ARGB32_Premultiplied )
4124 scanLine[widthIndex] = qRgba( opacity * qRed( myRgb ), opacity * qGreen( myRgb ), opacity * qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4126 scanLine[widthIndex] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4134 const int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
4135 const int alpha = ( radius < 1 ) ? 16 : ( radius > 17 ) ? 1 : tab[radius - 1];
4137 if ( image.format() != QImage::Format_ARGB32_Premultiplied
4138 && image.format() != QImage::Format_RGB32 )
4140 image = image.convertToFormat( QImage::Format_ARGB32_Premultiplied );
4143 const int r1 = rect.top();
4144 const int r2 = rect.bottom();
4145 const int c1 = rect.left();
4146 const int c2 = rect.right();
4148 const int bpl = image.bytesPerLine();
4156 i1 = i2 = ( QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3 );
4158 for (
int col = c1; col <= c2; col++ )
4160 p = image.scanLine( r1 ) + col * 4;
4161 for (
int i = i1; i <= i2; i++ )
4162 rgba[i] = p[i] << 4;
4165 for (
int j = r1; j < r2; j++, p += bpl )
4166 for (
int i = i1; i <= i2; i++ )
4167 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4170 for (
int row = r1; row <= r2; row++ )
4172 p = image.scanLine( row ) + c1 * 4;
4173 for (
int i = i1; i <= i2; i++ )
4174 rgba[i] = p[i] << 4;
4177 for (
int j = c1; j < c2; j++, p += 4 )
4178 for (
int i = i1; i <= i2; i++ )
4179 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4182 for (
int col = c1; col <= c2; col++ )
4184 p = image.scanLine( r2 ) + col * 4;
4185 for (
int i = i1; i <= i2; i++ )
4186 rgba[i] = p[i] << 4;
4189 for (
int j = r1; j < r2; j++, p -= bpl )
4190 for (
int i = i1; i <= i2; i++ )
4191 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4194 for (
int row = r1; row <= r2; row++ )
4196 p = image.scanLine( row ) + c2 * 4;
4197 for (
int i = i1; i <= i2; i++ )
4198 rgba[i] = p[i] << 4;
4201 for (
int j = c1; j < c2; j++, p -= 4 )
4202 for (
int i = i1; i <= i2; i++ )
4203 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4209 if ( alpha != 255 && alpha > 0 )
4213 const double alphaFactor = alpha / 255.;
4214 int r = 0, g = 0, b = 0;
4215 rgb.getRgb( &r, &g, &b );
4220 rgb.setRgb( r, g, b, alpha );
4222 else if ( alpha == 0 )
4224 rgb.setRgb( 0, 0, 0, 0 );
4233 if ( !simpleFill || !simpleLine )
4257 if ( simpleLine->
offset() )
4275 if ( order == Qt::AscendingOrder )
4289 const double dx = directionPoint.x() - startPoint.x();
4290 const double dy = directionPoint.y() - startPoint.y();
4291 const double length = std::sqrt( dx * dx + dy * dy );
4292 const double scaleFactor = distance / length;
4293 return QPointF( startPoint.x() + dx * scaleFactor, startPoint.y() + dy * scaleFactor );
4303 for (
int i = 0; i < svgPaths.size(); i++ )
4305 const QDir dir( svgPaths[i] );
4306 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4307 for (
const QString &item : svgSubPaths )
4309 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4312 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4313 for (
const QString &item : svgFiles )
4316 list.append( dir.path() +
'/' + item );
4328 QStringList svgPaths;
4329 svgPaths.append( directory );
4331 for (
int i = 0; i < svgPaths.size(); i++ )
4333 const QDir dir( svgPaths[i] );
4334 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4335 for (
const QString &item : svgSubPaths )
4337 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4340 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4341 for (
const QString &item : svgFiles )
4343 list.append( dir.path() +
'/' + item );
4355 if ( n.startsWith( QLatin1String(
"base64:" ) ) )
4359 if ( QFileInfo::exists( n ) )
4360 return QFileInfo( n ).canonicalFilePath();
4364 if ( name.contains( QLatin1String(
"://" ) ) )
4366 const QUrl url( name );
4367 if ( url.isValid() && !url.scheme().isEmpty() )
4369 if ( url.scheme().compare( QLatin1String(
"file" ), Qt::CaseInsensitive ) == 0 )
4372 name = url.toLocalFile();
4373 if ( QFile( name ).exists() )
4375 return QFileInfo( name ).canonicalFilePath();
4389 for (
int i = 0; i < svgPaths.size(); i++ )
4391 QString svgPath = svgPaths[i];
4392 if ( svgPath.endsWith( QChar(
'/' ) ) )
4403 const QString myLocalPath = svgPath + QDir::separator() + name;
4406 if ( QFile( myLocalPath ).exists() )
4409 return QFileInfo( myLocalPath ).canonicalFilePath();
4413 return pathResolver.
readPath( name );
4421 if ( p.startsWith( QLatin1String(
"base64:" ) ) )
4424 if ( !QFileInfo::exists( p ) )
4427 QString path = QFileInfo( p ).canonicalFilePath();
4431 bool isInSvgPaths =
false;
4432 for (
int i = 0; i < svgPaths.size(); i++ )
4434 const QString dir = QFileInfo( svgPaths[i] ).canonicalFilePath();
4436 if ( !dir.isEmpty() && path.startsWith( dir ) )
4438 path = path.mid( dir.size() + 1 );
4439 isInSvgPaths =
true;
4452 const double *srcX = line->
xData();
4453 const double *srcY = line->
yData();
4455 QPolygonF thisRes( count );
4456 QPointF *dest = thisRes.data();
4457 for (
int i = 0; i < count; ++i )
4459 *dest++ = QPointF( *srcX++, *srcY++ );
4466 if (
const QgsLineString *line = qgsgeometry_cast< const QgsLineString * >( curve ) )
4472 const std::unique_ptr< QgsLineString > straightened( curve->
curveToLine() );
4488 points << QPointF( ( *it ).x(), ( *it ).y() );
4492 points << QPointF( 0, 0 );
4494 return QList< QList<QPolygonF> >() << ( QList< QPolygonF >() << points );
4499 QList< QList<QPolygonF> > res;
4504 res << ( QList< QPolygonF >() <<
curveToPolygonF( qgsgeometry_cast< const QgsCurve * >( *it ) ) );
4512 QList< QList<QPolygonF> > res;
4516 QList<QPolygonF> thisPart;
4517 const QgsCurvePolygon *surface = qgsgeometry_cast< const QgsCurvePolygon * >( *it );
4535 return QList< QList<QPolygonF> >();
4538 return QList< QList<QPolygonF> >();
4545 double cx = 0, cy = 0;
4546 double area, sum = 0;
4547 for (
int i = points.count() - 1, j = 0; j < points.count(); i = j++ )
4549 const QPointF &p1 = points[i];
4550 const QPointF &p2 = points[j];
4551 area = p1.x() * p2.y() - p1.y() * p2.x();
4553 cx += ( p1.x() + p2.x() ) * area;
4554 cy += ( p1.y() + p2.y() ) * area;
4561 if ( points.count() >= 2 )
4562 return QPointF( ( points[0].x() + points[1].x() ) / 2, ( points[0].y() + points[1].y() ) / 2 );
4563 else if ( points.count() == 1 )
4571 return QPointF( cx, cy );
4578 if ( ( rings && rings->count() > 0 ) || !
pointInPolygon( points, centroid ) )
4580 unsigned int i, pointCount = points.count();
4582 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( points[i].x(), points[i].y() );
4588 for (
auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
4590 pointCount = ( *ringIt ).count();
4592 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( ( *ringIt )[i].x(), ( *ringIt )[i].y() );
4598 if ( !pointOnSurfaceGeom.
isNull() )
4601 centroid.
setX( point.
x() );
4602 centroid.
setY( point.
y() );
4607 return QPointF( centroid.
x(), centroid.
y() );
4612 bool inside =
false;
4614 const double x = point.x();
4615 const double y = point.y();
4617 for (
int i = 0, j = points.count() - 1; i < points.count(); i++ )
4619 const QPointF &p1 = points[i];
4620 const QPointF &p2 = points[j];
4625 if ( ( p1.y() < y && p2.y() >= y ) || ( p2.y() < y && p1.y() >= y ) )
4627 if ( p1.x() + ( y - p1.y() ) / ( p2.y() - p1.y() ) * ( p2.x() - p1.x() ) <= x )
4638 if ( polyline.size() < 2 )
4641 double totalLength = 0;
4642 auto it = polyline.begin();
4644 for ( ; it != polyline.end(); ++it )
4646 const QPointF p2 = *it;
4647 const double segmentLength = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4648 totalLength += segmentLength;
4656 if ( polyline.size() < 2 )
4659 double totalLength = 0;
4660 auto it = polyline.begin();
4662 std::vector< double > segmentLengths( polyline.size() - 1 );
4663 auto segmentLengthIt = segmentLengths.begin();
4664 for ( ; it != polyline.end(); ++it )
4666 const QPointF p2 = *it;
4667 *segmentLengthIt = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4668 totalLength += *segmentLengthIt;
4674 if ( startOffset >= 0 && totalLength <= startOffset )
4676 if ( endOffset < 0 && totalLength <= -endOffset )
4679 const double startDistance = startOffset < 0 ? totalLength + startOffset : startOffset;
4680 const double endDistance = endOffset <= 0 ? totalLength + endOffset : endOffset;
4681 QPolygonF substringPoints;
4682 substringPoints.reserve( polyline.size() );
4684 it = polyline.begin();
4685 segmentLengthIt = segmentLengths.begin();
4688 bool foundStart =
false;
4689 if (
qgsDoubleNear( startDistance, 0.0 ) || startDistance < 0 )
4691 substringPoints << p1;
4695 double distanceTraversed = 0;
4696 for ( ; it != polyline.end(); ++it )
4698 const QPointF p2 = *it;
4699 if ( distanceTraversed < startDistance && distanceTraversed + *segmentLengthIt > startDistance )
4702 const double distanceToStart = startDistance - distanceTraversed;
4703 double startX, startY;
4705 substringPoints << QPointF( startX, startY );
4708 if ( foundStart && ( distanceTraversed + *segmentLengthIt > endDistance ) )
4711 const double distanceToEnd = endDistance - distanceTraversed;
4714 if ( substringPoints.last() != QPointF( endX, endY ) )
4715 substringPoints << QPointF( endX, endY );
4717 else if ( foundStart )
4719 if ( substringPoints.last() != QPointF( p2.x(), p2.y() ) )
4720 substringPoints << QPointF( p2.x(), p2.y() );
4723 distanceTraversed += *segmentLengthIt;
4724 if ( distanceTraversed > endDistance )
4731 if ( ( substringPoints.size() < 2 ) || ( substringPoints.size() == 2 && substringPoints.at( 0 ) == substringPoints.at( 1 ) ) )
4734 return substringPoints;
4739 double vertexAngle = M_PI - ( std::atan2( p3.y() - p2.y(), p3.x() - p2.x() ) - std::atan2( p2.y() - p1.y(), p2.x() - p1.x() ) );
4743 return vertexAngle < M_PI * 135.0 / 180.0 || vertexAngle > M_PI * 225.0 / 180.0;
4748 target.reserve( target.size() + line.size() );
4749 for (
const QPointF &pt : line )
4751 if ( !target.empty() && target.last() == pt )
4760 if ( fieldOrExpression.isEmpty() )
4795 QList<double> breaks;
4798 breaks.append( maximum );
4802 const int minimumCount =
static_cast< int >( classes ) / 3;
4803 const double shrink = 0.75;
4804 const double highBias = 1.5;
4805 const double adjustBias = 0.5 + 1.5 * highBias;
4806 const int divisions = classes;
4807 const double h = highBias;
4810 const double dx = maximum - minimum;
4820 cell = std::max( std::fabs( minimum ), std::fabs( maximum ) );
4821 if ( adjustBias >= 1.5 * h + 0.5 )
4823 U = 1 + ( 1.0 / ( 1 + h ) );
4827 U = 1 + ( 1.5 / ( 1 + adjustBias ) );
4829 small = dx < ( cell * U * std::max( 1, divisions ) * 1e-07 * 3.0 );
4836 cell = 9 + cell / 10;
4837 cell = cell * shrink;
4839 if ( minimumCount > 1 )
4841 cell = cell / minimumCount;
4847 if ( divisions > 1 )
4849 cell = cell / divisions;
4852 if ( cell < 20 * 1e-07 )
4857 const double base = std::pow( 10.0, std::floor( std::log10( cell ) ) );
4859 if ( ( 2 * base ) - cell < h * ( cell - unit ) )
4862 if ( ( 5 * base ) - cell < adjustBias * ( cell - unit ) )
4865 if ( ( 10.0 * base ) - cell < h * ( cell - unit ) )
4872 int start = std::floor( minimum / unit + 1e-07 );
4873 int end = std::ceil( maximum / unit - 1e-07 );
4876 while ( start * unit > minimum + ( 1e-07 * unit ) )
4880 while ( end * unit < maximum - ( 1e-07 * unit ) )
4888 int k = std::floor( 0.5 + end - start );
4889 if ( k < minimumCount )
4891 k = minimumCount - k;
4895 start = start - k / 2 + k % 2;
4899 start = start - k / 2;
4900 end = end + k / 2 + k % 2;
4903 const double minimumBreak = start * unit;
4905 const int count = end - start;
4907 breaks.reserve( count );
4908 for (
int i = 1; i < count + 1; i++ )
4910 breaks.append( minimumBreak + i * unit );
4913 if ( breaks.isEmpty() )
4916 if ( breaks.first() < minimum )
4918 breaks[0] = minimum;
4920 if ( breaks.last() > maximum )
4922 breaks[breaks.count() - 1] = maximum;
4927 if ( minimum < 0.0 && maximum > 0.0 )
4929 QList<double> breaksMinusZero;
4930 for (
int i = 0; i < breaks.count(); i++ )
4932 breaksMinusZero.append( breaks[i] - 0.0 );
4935 for (
int i = 1; i < breaks.count(); i++ )
4937 if ( std::abs( breaksMinusZero[i] ) < std::abs( breaksMinusZero[i - 1] ) )
4940 breaks[posOfMin] = 0.0;
4949 bool roundToUnit =
false;
4952 if ( props.contains( QStringLiteral(
"uomScale" ) ) )
4955 scale = props.value( QStringLiteral(
"uomScale" ) ).toDouble( &ok );
4964 if ( props.value( QStringLiteral(
"uom" ) ) == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
4989 scale = 1 / 0.28 * 25.4;
5013 double rescaled = size * scale;
5018 rescaled = std::round( rescaled );
5025 const double x =
rescaleUom( point.x(), unit, props );
5026 const double y =
rescaleUom( point.y(), unit, props );
5027 return QPointF( x, y );
5032 QVector<qreal> result;
5033 QVector<qreal>::const_iterator it = array.constBegin();
5034 for ( ; it != array.constEnd(); ++it )
5036 result.append(
rescaleUom( *it, unit, props ) );
5043 if ( !props.value( QStringLiteral(
"scaleMinDenom" ), QString() ).toString().isEmpty() )
5045 QDomElement scaleMinDenomElem = doc.createElement( QStringLiteral(
"se:MinScaleDenominator" ) );
5046 scaleMinDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMinDenom" ) ).toString().toDouble() ) ) );
5047 ruleElem.appendChild( scaleMinDenomElem );
5050 if ( !props.value( QStringLiteral(
"scaleMaxDenom" ), QString() ).toString().isEmpty() )
5052 QDomElement scaleMaxDenomElem = doc.createElement( QStringLiteral(
"se:MaxScaleDenominator" ) );
5053 scaleMaxDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMaxDenom" ) ).toString().toDouble() ) ) );
5054 ruleElem.appendChild( scaleMaxDenomElem );
5063 const double parentScaleMinDenom = props.value( QStringLiteral(
"scaleMinDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
5064 if ( !ok || parentScaleMinDenom <= 0 )
5065 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( mScaleMinDenom );
5067 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( std::max( parentScaleMinDenom, mScaleMinDenom ) );
5073 const double parentScaleMaxDenom = props.value( QStringLiteral(
"scaleMaxDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
5074 if ( !ok || parentScaleMaxDenom <= 0 )
5075 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( mScaleMaxDenom );
5077 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( std::min( parentScaleMaxDenom, mScaleMaxDenom ) );
5085 if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
5087 scale = 1.0 / 0.00028;
5089 else if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
5091 scale = 304.8 / 0.28;
5098 return size * scale;
5107 SymbolLayerVisitor(
const QSet<QgsSymbolLayerId> &layerIds )
5108 : mSymbolLayerIds( layerIds )
5121 void visitSymbol(
const QgsSymbol *symbol,
const QString &identifier, QVector<int> rootPath )
5125 QVector<int> indexPath = rootPath;
5126 indexPath.append( idx );
5129 if ( mSymbolLayerIds.contains(
QgsSymbolLayerId( mCurrentRuleKey + identifier, indexPath ) ) )
5131 mSymbolLayers.insert( sl );
5137 visitSymbol( subSymbol, identifier, indexPath );
5146 if ( symbolEntity->symbol() )
5148 visitSymbol( symbolEntity->symbol(), leaf.
identifier, {} );
5154 QString mCurrentRuleKey;
5155 const QSet<QgsSymbolLayerId> &mSymbolLayerIds;
5156 QSet<const QgsSymbolLayer *> mSymbolLayers;
5160 SymbolLayerVisitor visitor( symbolLayerIds );
5161 renderer->
accept( &visitor );
5162 return visitor.mSymbolLayers;
5170 SymbolRefreshRateVisitor()
5182 void visitSymbol(
const QgsSymbol *symbol )
5199 if ( refreshRate == -1 || ( animatedMarker->frameRate() > refreshRate ) )
5200 refreshRate = animatedMarker->frameRate();
5204 visitSymbol( subSymbol );
5212 if (
QgsSymbol *symbol = qgis::down_cast<const QgsStyleSymbolEntity *>( leaf.
entity )->symbol() )
5214 visitSymbol( symbol );
5220 double refreshRate = -1;
5223 SymbolRefreshRateVisitor visitor;
5224 renderer->
accept( &visitor );
5225 return visitor.refreshRate;
5230 if ( !s || !context )
5256 size = markerSymbol->
size( *context );
5258 else if ( lineSymbol )
5260 size = lineSymbol->
width( *context );
5272 if ( minSize > 0 && size < minSize )
5276 else if ( maxSize > 0 && size > maxSize )
5295 else if ( lineSymbol )
5310 QMap<QString, QgsProperty>::const_iterator paramIt = propertiesMap.constBegin();
5311 for ( ; paramIt != propertiesMap.constEnd(); ++paramIt )
5313 properties.insert( paramIt.key(), paramIt.value().valueAsString( context ) );
5321 angleRad = std::fmod( angleRad, M_PI * 2 );
5325 angleRad += M_PI * 2;
5329 struct rationalTangent
5341 static const QList<rationalTangent> __rationalTangents
5343 { 1, 57, 0.01754206006 },
5344 { 3, 86, 0.03486958155 },
5345 { 1, 19, 0.05258306161 },
5346 { 3, 43, 0.06965457373 },
5347 { 7, 80, 0.08727771295 },
5348 { 2, 19, 0.1048769387 },
5349 { 7, 57, 0.1221951707 },
5350 { 9, 64, 0.1397088743 },
5351 { 13, 82, 0.157228051 },
5352 { 3, 17, 0.174672199 },
5353 { 7, 36, 0.1920480172 },
5354 { 17, 80, 0.209385393 },
5355 { 3, 13, 0.2267988481 },
5356 { 1, 4, 0.2449786631 },
5357 { 26, 97, 0.2618852647 },
5358 { 27, 94, 0.2797041525 },
5359 { 26, 85, 0.2968446734 },
5360 { 13, 40, 0.3142318991 },
5361 { 21, 61, 0.3315541619 },
5362 { 4, 11, 0.3487710036 },
5363 { 38, 99, 0.3664967859 },
5364 { 40, 99, 0.383984624 },
5365 { 31, 73, 0.4015805401 },
5366 { 41, 92, 0.4192323938 },
5367 { 7, 15, 0.4366271598 },
5368 { 20, 41, 0.4538440015 },
5369 { 27, 53, 0.4711662643 },
5370 { 42, 79, 0.4886424026 },
5371 { 51, 92, 0.5061751436 },
5372 { 56, 97, 0.5235757641 },
5373 { 3, 5, 0.5404195003 },
5374 { 5, 8, 0.5585993153 },
5375 { 50, 77, 0.5759185996 },
5376 { 29, 43, 0.5933501462 },
5377 { 7, 10, 0.6107259644 },
5378 { 69, 95, 0.6281701124 },
5379 { 52, 69, 0.6458159195 },
5380 { 25, 32, 0.6632029927 },
5381 { 17, 21, 0.6805212247 },
5382 { 73, 87, 0.6981204504 },
5383 { 73, 84, 0.7154487784 },
5384 { 9, 10, 0.7328151018 },
5385 { 83, 89, 0.7505285818 },
5386 { 28, 29, 0.7678561033 },
5387 { 1, 1, 0.7853981634 },
5388 { 29, 28, 0.8029402235 },
5389 { 89, 83, 0.820267745 },
5390 { 10, 9, 0.837981225 },
5391 { 107, 93, 0.855284165 },
5392 { 87, 73, 0.8726758763 },
5393 { 121, 98, 0.8900374031 },
5394 { 32, 25, 0.9075933341 },
5395 { 69, 52, 0.9249804073 },
5396 { 128, 93, 0.9424647244 },
5397 { 10, 7, 0.9600703624 },
5398 { 43, 29, 0.9774461806 },
5399 { 77, 50, 0.9948777272 },
5400 { 8, 5, 1.012197011 },
5401 { 163, 98, 1.029475114 },
5402 { 168, 97, 1.047174539 },
5403 { 175, 97, 1.064668696 },
5404 { 126, 67, 1.082075603 },
5405 { 157, 80, 1.099534652 },
5406 { 203, 99, 1.117049384 },
5407 { 193, 90, 1.134452855 },
5408 { 146, 65, 1.151936673 },
5409 { 139, 59, 1.169382787 },
5410 { 99, 40, 1.186811703 },
5411 { 211, 81, 1.204257817 },
5412 { 272, 99, 1.221730164 },
5413 { 273, 94, 1.239188479 },
5414 { 277, 90, 1.25664606 },
5415 { 157, 48, 1.274088705 },
5416 { 279, 80, 1.291550147 },
5417 { 362, 97, 1.308990773 },
5418 { 373, 93, 1.326448578 },
5419 { 420, 97, 1.343823596 },
5420 { 207, 44, 1.361353157 },
5421 { 427, 83, 1.378810994 },
5422 { 414, 73, 1.396261926 },
5423 { 322, 51, 1.413716057 },
5424 { 185, 26, 1.431170275 },
5425 { 790, 97, 1.448623034 },
5426 { 333, 35, 1.466075711 },
5427 { 1063, 93, 1.483530284 },
5428 { 1330, 93, 1.500985147 },
5429 { 706, 37, 1.518436297 },
5430 { 315, 11, 1.535889876 },
5431 { 3953, 69, 1.553343002 },
5437 static const QList<rationalTangent> rationalTangents
5439 { 1, 10, qDegreesToRadians( 5.71059 ) },
5440 { 1, 5, qDegreesToRadians( 11.3099 ) },
5441 { 1, 4, qDegreesToRadians( 14.0362 ) },
5442 { 1, 4, qDegreesToRadians( 18.4349 ) },
5443 { 1, 2, qDegreesToRadians( 26.5651 ) },
5444 { 2, 3, qDegreesToRadians( 33.6901 ) },
5445 { 1, 1, qDegreesToRadians( 45.0 ) },
5446 { 3, 2, qDegreesToRadians( 56.3099 ) },
5447 { 2, 1, qDegreesToRadians( 63.4349 ) },
5448 { 3, 1, qDegreesToRadians( 71.5651 ) },
5449 { 4, 1, qDegreesToRadians( 75.9638 ) },
5450 { 10, 1, qDegreesToRadians( 84.2894 ) },
5453 const int quadrant {
static_cast<int>( angleRad / M_PI_2 ) };
5454 Q_ASSERT( quadrant >= 0 && quadrant <= 3 );
5466 angleRad -= M_PI / 2;
5476 angleRad -= M_PI + M_PI_2;
5498 for (
int idx = 0; idx < rationalTangents.count(); ++idx )
5500 const auto item = rationalTangents.at( idx );
5501 if (
qgsDoubleNear( item.angle, angleRad, 10E-3 ) || item.angle > angleRad )
5508 const rationalTangent bTan { rationalTangents.at( rTanIdx ) };
5509 angleRad = bTan.angle;
5510 const double k { bTan.q *height *width / std::cos( angleRad ) };
5511 const int hcfH { std::gcd( bTan.p * height, bTan.q * width ) };
5512 const int hcfW { std::gcd( bTan.q * height, bTan.p * width ) };
5513 const int W1 {
static_cast<int>( std::round( k / hcfW ) ) };
5514 const int H1 {
static_cast<int>( std::round( k / hcfH ) ) };
5527 angleRad += M_PI / 2;
5540 angleRad += M_PI + M_PI_2;
5551template <
typename Functor>
5554 sl->
setId( generateId() );
5562template <
typename Functor>
5590 if ( clipGeometries.empty() )
5593 if ( bounds.isNull() )
5594 return clipGeometries;
5598 clipGeometries.erase(
5599 std::remove_if( clipGeometries.begin(), clipGeometries.end(), [&boundsRect](
const QgsGeometry & geometry )
5601 return !geometry.boundingBoxIntersects( boundsRect );
5602 } ), clipGeometries.end() );
5604 return clipGeometries;
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.
@ 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.
@ Flat
Flat cap (in line with start/end of line)
@ 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.
virtual bool readXml(const QDomElement &collectionElem, const QgsPropertiesDefinition &definitions)
Reads property collection state from an XML element.
virtual bool writeXml(QDomElement &collectionElem, const QgsPropertiesDefinition &definitions) const
Writes the current state of the property collection into an XML element.
Animated marker symbol layer class.
static QgsPaintEffectRegistry * paintEffectRegistry()
Returns the application's paint effect registry, used for managing paint effects.
static QgsSymbolLayerRegistry * symbolLayerRegistry()
Returns the application's symbol layer registry, used for managing symbol layers.
static QStringList svgPaths()
Returns the paths to svg directories.
HeadType
Possible head types.
ArrowType
Possible arrow types.
static QString typeString()
Returns the string identifier for QgsColorBrewerColorRamp.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Returns a new QgsColorBrewerColorRamp color ramp created using the properties encoded in a string map...
Abstract base class for color ramps.
virtual QColor color(double value) const =0
Returns the color corresponding to a specified value.
virtual double value(int index) const =0
Returns relative value between [0,1] of color at specified index.
virtual QVariantMap properties() const =0
Returns a string map containing all the color ramp's properties.
virtual QString type() const =0
Returns a string representing the color ramp type.
static QColor colorFromString(const QString &string)
Decodes a string into a color value.
static QString colorToString(const QColor &color)
Encodes a color into a string value.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates the symbol layer.
static QString typeString()
Returns the string identifier for QgsCptCityColorRamp.
Curve polygon geometry type.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
Abstract base class for curved geometry type.
virtual QgsLineString * curveToLine(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const =0
Returns a new line string geometry corresponding to a segmentized approximation of the curve.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
bool hasFeature() const
Returns true if the context has a feature associated with it.
An expression node which takes it 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.
Class for 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.
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
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.
QgsAbstractGeometry::const_part_iterator const_parts_begin() const
Returns STL-style const iterator pointing to the first part of the geometry.
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.
QgsPolylineXY asPolyline() const
Returns the contents of the geometry as a polyline.
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
Qgis::GeometryOperationResult addRing(const QVector< QgsPointXY > &ring)
Adds a new ring to this geometry.
QgsMultiPolylineXY asMultiPolyline() const
Returns the contents of the geometry as a multi-linestring.
static QgsGeometry fromPolygonXY(const QgsPolygonXY &polygon)
Creates a new geometry from a QgsPolygonXY.
QgsGeometry buffer(double distance, int segments) const
Returns a buffer region around this geometry having the given width and with a specified number of se...
QgsAbstractGeometry::const_part_iterator const_parts_end() const
Returns STL-style iterator pointing to the imaginary part after the last part of the geometry.
QgsAbstractGeometry::vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
QgsAbstractGeometry::vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsColorRamp from a map of properties.
static QString typeString()
Returns the string identifier for QgsGradientColorRamp.
Represents a patch shape for use in map legends.
static QString typeString()
Returns the string identifier for QgsLimitedRandomColorRamp.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Returns a new QgsLimitedRandomColorRamp color ramp created using the properties encoded in a string m...
Line string geometry type, with support for z-dimension and m-values.
const double * yData() const
Returns a const pointer to the y vertex data.
const double * xData() const
Returns a const pointer to the x vertex data.
int numPoints() const override
Returns the number of points in the curve.
Abstract base class for line symbol layers.
const QgsMapUnitScale & widthMapUnitScale() const
@ AllRings
Render both exterior and interior rings.
RenderRingFilter ringFilter() const
Returns the line symbol layer's ring filter, which controls which rings are rendered when the line sy...
virtual double width() const
Returns the estimated width for the line symbol layer.
double offset() const
Returns the line's offset.
Qgis::RenderUnit widthUnit() const
Returns the units for the line's width.
A line symbol type, for rendering LineString and MultiLineString geometries.
void setWidthUnit(Qgis::RenderUnit unit) const
Sets the width units for the whole symbol (including all symbol layers).
void setWidth(double width) const
Sets the width for the whole line 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.
void setSize(double size) const
Sets the size for the whole symbol.
double size() const
Returns the estimated size for the whole symbol, which is the maximum size of all marker symbol layer...
void setSizeUnit(Qgis::RenderUnit unit) const
Sets the size units for the whole symbol (including all symbol layers).
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.
A class to represent a 2D point.
void setY(double y)
Sets the point's y-coordinate.
void setX(double x)
Sets the point's x-coordinate.
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 a 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.
The class is used as a container of context for various read/write operations on other 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.
void setForceVectorOutput(bool force)
Sets whether rendering operations should use vector operations instead of any faster raster shortcuts...
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 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 class for filling symbols with a repeated SVG file.
Stores properties relating to a screen.
double devicePixelRatio() const
Returns the ratio between physical pixels and device-independent pixels for the screen.
bool isValid() const
Returns true if the properties are valid.
void updateRenderContextForScreen(QgsRenderContext &context) const
Updates the settings in a render context to match the screen settings.
Renders polygons using a single fill and stroke color.
void setStrokeWidthMapUnitScale(const QgsMapUnitScale &scale)
void setStrokeWidthUnit(Qgis::RenderUnit unit)
Sets the units for the width of the fill's stroke.
void setPenJoinStyle(Qt::PenJoinStyle style)
void setStrokeWidth(double strokeWidth)
void setStrokeStyle(Qt::PenStyle strokeStyle)
void setStrokeColor(const QColor &strokeColor) override
Sets the stroke color for the symbol layer.
A simple line symbol layer, which renders lines using a line in a variety of styles (e....
bool tweakDashPatternOnCorners() const
Returns true if dash patterns tweaks should be applied on sharp corners, to ensure that a double-leng...
Qt::PenJoinStyle penJoinStyle() const
Returns the pen join style used to render the line (e.g.
double trimDistanceStart() const
Returns the trim distance for the start of the line, which dictates a length from the start of the li...
double trimDistanceEnd() const
Returns the trim distance for the end of the line, which dictates a length from the end of the line a...
bool useCustomDashPattern() const
Returns true if the line uses a custom dash pattern.
Qt::PenStyle penStyle() const
Returns the pen style used to render the line (e.g.
double dashPatternOffset() const
Returns the dash pattern offset, which dictates how far along the dash pattern the pattern should sta...
bool drawInsidePolygon() const
Returns true if the line should only be drawn inside polygons, and any portion of the line which fall...
bool alignDashPattern() const
Returns true if dash patterns should be aligned to the start and end of lines, by applying subtle twe...
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.
void setIsAnimated(bool animated)
Sets whether the symbol is animated.
void setFrameRate(double rate)
Sets the symbol animation frame rate (in frames per second).
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 is not usable (when a ...
QgsSymbolLayer * createSymbolLayerFromSld(const QString &name, QDomElement &element) const
create a new instance of symbol layer given symbol layer name and SLD
QgsSymbolLayer * createSymbolLayer(const QString &name, const QVariantMap &properties=QVariantMap()) const
create a new instance of symbol layer given symbol layer name and properties
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.
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 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 QgsSymbol * symbolFromMimeData(const QMimeData *data)
Attempts to parse mime data as a symbol.
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 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 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 bool createFunctionElement(QDomDocument &doc, QDomElement &element, const QString &function)
static QColor decodeColor(const QString &str)
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 QgsColorRamp * loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
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 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 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 QgsNamedColorList colorListFromMimeData(const QMimeData *data)
Attempts to parse mime data as a list of named colors.
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 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 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 void createOpacityElement(QDomDocument &doc, QDomElement &element, const QString &alphaFunc)
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 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 QDomElement saveColorRamp(const QString &name, QgsColorRamp *ramp, QDomDocument &doc)
Encodes a color ramp's settings to an XML element.
static bool opacityFromSldElement(QDomElement &element, QString &alphaFunc)
static QString encodeSldFontWeight(int weight)
static void externalMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &path, const QString &format, int *markIndex=nullptr, const QColor &color=QColor(), double size=-1)
static QMimeData * colorListToMimeData(const QgsNamedColorList &colorList, bool allFormats=true)
Creates mime data from a list of named colors.
static Qt::BrushStyle decodeBrushStyle(const QString &str)
static void lineToSld(QDomDocument &doc, QDomElement &element, Qt::PenStyle penStyle, const QColor &color, double width=-1, const Qt::PenJoinStyle *penJoinStyle=nullptr, const Qt::PenCapStyle *penCapStyle=nullptr, const QVector< qreal > *customDashPattern=nullptr, double dashOffset=0.0)
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)
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 QgsSymbol * loadSymbol(const QDomElement &element, const QgsReadWriteContext &context)
Attempts to load a symbol from a DOM element.
static 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 QString colorToName(const QColor &color)
Returns a friendly display name for a color.
static int decodeSldAlpha(const QString &str)
static QString encodeSldLineJoinStyle(Qt::PenJoinStyle style)
static void createDisplacementElement(QDomDocument &doc, QDomElement &element, QPointF offset)
static QString svgSymbolNameToPath(const QString &name, const QgsPathResolver &pathResolver)
Determines an SVG symbol's path from its name.
static void drawStippledBackground(QPainter *painter, QRect rect)
static QList< QColor > parseColorList(const QString &colorStr)
Attempts to parse a string as a list of colors using a variety of common formats, including hex codes...
static QString encodeColor(const QColor &color)
static QgsSymbolLayer * loadSymbolLayer(QDomElement &element, const QgsReadWriteContext &context)
Reads and returns symbol layer from XML. Caller is responsible for deleting the returned object.
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 QMimeData * symbolToMimeData(const QgsSymbol *symbol)
Creates new mime data from a symbol.
static QString encodeSldFontStyle(QFont::Style style)
static QColor colorFromMimeData(const QMimeData *data, bool &hasAlpha)
Attempts to parse mime data as a color.
static int decodeSldFontWeight(const QString &str)
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
static void fillToSld(QDomDocument &doc, QDomElement &element, Qt::BrushStyle brushStyle, const QColor &color=QColor())
static double polylineLength(const QPolygonF &polyline)
Returns the total length of a polyline.
static bool hasExternalGraphicV2(QDomElement &element, const QString format=QString())
Checks if element contains an ExternalGraphic element, if the optional format is specified it will al...
static Qgis::RenderUnit decodeSldUom(const QString &str, double *scaleFactor=nullptr)
Decodes a SLD unit of measure string to a render unit.
static void createGeometryElement(QDomDocument &doc, QDomElement &element, const QString &geomFunc)
static QgsArrowSymbolLayer::ArrowType decodeArrowType(const QVariant &value, bool *ok=nullptr)
Decodes a value representing an arrow type.
static bool needSvgMarker(QDomElement &element)
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 void wellKnownMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &name, const QColor &color, const QColor &strokeColor, Qt::PenStyle strokeStyle, double strokeWidth=-1, double size=-1)
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 void createRotationElement(QDomDocument &doc, QDomElement &element, const QString &rotationFunc)
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 void labelTextToSld(QDomDocument &doc, QDomElement &element, const QString &label, const QFont &font, const QColor &color=QColor(), double size=-1)
static QgsSymbolLayer * createMarkerLayerFromSld(QDomElement &element)
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 QString encodePenJoinStyle(Qt::PenJoinStyle style)
static QgsStringMap getVendorOptionList(QDomElement &element)
static QIcon symbolPreviewIcon(const QgsSymbol *symbol, QSize size, int padding=0, QgsLegendPatchShape *shape=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Returns an icon preview for a color ramp.
static QMimeData * colorToMimeData(const QColor &color)
Creates mime data from a color.
static bool condenseFillAndOutline(QgsFillSymbolLayer *fill, QgsLineSymbolLayer *outline)
Attempts to condense a fill and outline layer, by moving the outline layer to the fill symbol's strok...
static QPointF decodePoint(const QString &string)
Decodes a QSizeF from a string.
static QPolygonF polylineSubstring(const QPolygonF &polyline, double startOffset, double endOffset)
Returns the substring of a polyline which starts at startOffset from the beginning of the line and en...
static QgsSymbolLayer * createLineLayerFromSld(QDomElement &element)
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 QgsSymbolLayer * createFillLayerFromSld(QDomElement &element)
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 QgsExpression * fieldOrExpressionToExpression(const QString &fieldOrExpression)
Returns a new valid expression instance for given field or expression string.
static QSizeF decodeSize(const QString &string)
Decodes a QSizeF from a string.
static QString encodeRealVector(const QVector< qreal > &v)
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.
void setPaintEffect(QgsPaintEffect *effect)
Sets the current paint effect for the layer.
void setRenderingPass(int renderingPass)
Specifies the rendering pass in which this symbol layer should be rendered.
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.
void setEnabled(bool enabled)
Sets whether symbol layer is enabled and should be drawn.
virtual QVariantMap properties() const =0
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void setUserFlags(Qgis::SymbolLayerUserFlags flags)
Sets user-controlled flags which control the symbol layer's behavior.
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 void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the layer.
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.
void setLocked(bool locked)
Sets whether the layer's colors are locked.
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.
void setOriginalGeometryType(Qgis::GeometryType type)
Sets the geometry type for the original feature geometry being rendered.
Abstract base class for all rendered symbols.
void setOutputUnit(Qgis::RenderUnit unit) const
Sets the units to use for sizes and widths within the symbol.
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.
void setMapUnitScale(const QgsMapUnitScale &scale) const
Sets the map unit scale for the symbol.
bool clipFeaturesToExtent() const
Returns whether features drawn by the symbol will be clipped to the render context's extent.
void setFlags(Qgis::SymbolFlags flags)
Sets flags for the symbol.
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.
void setOpacity(qreal opacity)
Sets the opacity for the symbol.
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.
void setBufferSettings(QgsSymbolBufferSettings *settings)
Sets a the symbol buffer settings, which control an optional "halo" effect around the symbol.
bool forceRHR() const
Returns true if polygon features drawn by the symbol will be reoriented to follow the standard right-...
void setClipFeaturesToExtent(bool clipFeaturesToExtent)
Sets whether features drawn by the symbol should be clipped to the render context's extent.
void setForceRHR(bool force)
Sets whether polygon features drawn by the symbol should be reoriented to follow the standard right-h...
static Q_INVOKABLE Qgis::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from 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.
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)
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)
QList< QPair< QColor, QString > > QgsNamedColorList
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.