49#include <QDomDocument>
59#include <QRegularExpression>
62#define POINTS_TO_MM 2.83464567
66 return QStringLiteral(
"%1,%2,%3,%4" ).arg( color.red() ).arg( color.green() ).arg( color.blue() ).arg( color.alpha() );
71 const QStringList lst =
str.split(
',' );
72 if ( lst.count() < 3 )
76 int red, green, blue, alpha;
78 green = lst[1].toInt();
79 blue = lst[2].toInt();
81 if ( lst.count() > 3 )
83 alpha = lst[3].toInt();
85 return QColor( red, green, blue, alpha );
90 return QString::number( alpha / 255.0,
'g', 2 );
96 double alpha =
str.toDouble( &ok );
97 if ( !ok || alpha > 1 )
108 case QFont::StyleNormal:
109 return QStringLiteral(
"normal" );
110 case QFont::StyleItalic:
111 return QStringLiteral(
"italic" );
112 case QFont::StyleOblique:
113 return QStringLiteral(
"oblique" );
121 if (
str == QLatin1String(
"normal" ) )
return QFont::StyleNormal;
122 if (
str == QLatin1String(
"italic" ) )
return QFont::StyleItalic;
123 if (
str == QLatin1String(
"oblique" ) )
return QFont::StyleOblique;
124 return QFont::StyleNormal;
129 if ( weight == 50 )
return QStringLiteral(
"normal" );
130 if ( weight == 75 )
return QStringLiteral(
"bold" );
134 if ( weight < 0 )
return QStringLiteral(
"100" );
135 if ( weight > 99 )
return QStringLiteral(
"900" );
136 return QString::number( weight * 800 / 99 + 100 );
142 const int weight =
str.toInt( &ok );
144 return static_cast< int >( QFont::Normal );
148 if ( weight > 900 )
return 99;
149 if ( weight < 100 )
return 0;
150 return ( weight - 100 ) * 99 / 800;
158 return QStringLiteral(
"no" );
160 return QStringLiteral(
"solid" );
162 return QStringLiteral(
"dash" );
164 return QStringLiteral(
"dot" );
165 case Qt::DashDotLine:
166 return QStringLiteral(
"dash dot" );
167 case Qt::DashDotDotLine:
168 return QStringLiteral(
"dash dot dot" );
170 return QStringLiteral(
"???" );
176 if (
str == QLatin1String(
"no" ) )
return Qt::NoPen;
177 if (
str == QLatin1String(
"solid" ) )
return Qt::SolidLine;
178 if (
str == QLatin1String(
"dash" ) )
return Qt::DashLine;
179 if (
str == QLatin1String(
"dot" ) )
return Qt::DotLine;
180 if (
str == QLatin1String(
"dash dot" ) )
return Qt::DashDotLine;
181 if (
str == QLatin1String(
"dash dot dot" ) )
return Qt::DashDotDotLine;
182 return Qt::SolidLine;
190 return QStringLiteral(
"bevel" );
192 return QStringLiteral(
"miter" );
194 return QStringLiteral(
"round" );
196 return QStringLiteral(
"???" );
202 const QString cleaned =
str.toLower().trimmed();
203 if ( cleaned == QLatin1String(
"bevel" ) )
204 return Qt::BevelJoin;
205 if ( cleaned == QLatin1String(
"miter" ) )
206 return Qt::MiterJoin;
207 if ( cleaned == QLatin1String(
"round" ) )
208 return Qt::RoundJoin;
209 return Qt::BevelJoin;
217 return QStringLiteral(
"bevel" );
219 return QStringLiteral(
"mitre" );
221 return QStringLiteral(
"round" );
229 if (
str == QLatin1String(
"bevel" ) )
return Qt::BevelJoin;
230 if (
str == QLatin1String(
"mitre" ) )
return Qt::MiterJoin;
231 if (
str == QLatin1String(
"round" ) )
return Qt::RoundJoin;
232 return Qt::BevelJoin;
240 return QStringLiteral(
"square" );
242 return QStringLiteral(
"flat" );
244 return QStringLiteral(
"round" );
246 return QStringLiteral(
"???" );
252 if (
str == QLatin1String(
"square" ) )
return Qt::SquareCap;
253 if (
str == QLatin1String(
"flat" ) )
return Qt::FlatCap;
254 if (
str == QLatin1String(
"round" ) )
return Qt::RoundCap;
255 return Qt::SquareCap;
263 return QStringLiteral(
"square" );
265 return QStringLiteral(
"butt" );
267 return QStringLiteral(
"round" );
275 if (
str == QLatin1String(
"square" ) )
return Qt::SquareCap;
276 if (
str == QLatin1String(
"butt" ) )
return Qt::FlatCap;
277 if (
str == QLatin1String(
"round" ) )
return Qt::RoundCap;
278 return Qt::SquareCap;
285 case Qt::SolidPattern :
286 return QStringLiteral(
"solid" );
287 case Qt::HorPattern :
288 return QStringLiteral(
"horizontal" );
289 case Qt::VerPattern :
290 return QStringLiteral(
"vertical" );
291 case Qt::CrossPattern :
292 return QStringLiteral(
"cross" );
293 case Qt::BDiagPattern :
294 return QStringLiteral(
"b_diagonal" );
295 case Qt::FDiagPattern :
296 return QStringLiteral(
"f_diagonal" );
297 case Qt::DiagCrossPattern :
298 return QStringLiteral(
"diagonal_x" );
299 case Qt::Dense1Pattern :
300 return QStringLiteral(
"dense1" );
301 case Qt::Dense2Pattern :
302 return QStringLiteral(
"dense2" );
303 case Qt::Dense3Pattern :
304 return QStringLiteral(
"dense3" );
305 case Qt::Dense4Pattern :
306 return QStringLiteral(
"dense4" );
307 case Qt::Dense5Pattern :
308 return QStringLiteral(
"dense5" );
309 case Qt::Dense6Pattern :
310 return QStringLiteral(
"dense6" );
311 case Qt::Dense7Pattern :
312 return QStringLiteral(
"dense7" );
314 return QStringLiteral(
"no" );
316 return QStringLiteral(
"???" );
322 if (
str == QLatin1String(
"solid" ) )
return Qt::SolidPattern;
323 if (
str == QLatin1String(
"horizontal" ) )
return Qt::HorPattern;
324 if (
str == QLatin1String(
"vertical" ) )
return Qt::VerPattern;
325 if (
str == QLatin1String(
"cross" ) )
return Qt::CrossPattern;
326 if (
str == QLatin1String(
"b_diagonal" ) )
return Qt::BDiagPattern;
327 if (
str == QLatin1String(
"f_diagonal" ) )
return Qt::FDiagPattern;
328 if (
str == QLatin1String(
"diagonal_x" ) )
return Qt::DiagCrossPattern;
329 if (
str == QLatin1String(
"dense1" ) )
return Qt::Dense1Pattern;
330 if (
str == QLatin1String(
"dense2" ) )
return Qt::Dense2Pattern;
331 if (
str == QLatin1String(
"dense3" ) )
return Qt::Dense3Pattern;
332 if (
str == QLatin1String(
"dense4" ) )
return Qt::Dense4Pattern;
333 if (
str == QLatin1String(
"dense5" ) )
return Qt::Dense5Pattern;
334 if (
str == QLatin1String(
"dense6" ) )
return Qt::Dense6Pattern;
335 if (
str == QLatin1String(
"dense7" ) )
return Qt::Dense7Pattern;
336 if (
str == QLatin1String(
"no" ) )
return Qt::NoBrush;
337 return Qt::SolidPattern;
344 case Qt::CrossPattern:
345 return QStringLiteral(
"cross" );
346 case Qt::DiagCrossPattern:
347 return QStringLiteral(
"x" );
354 return QStringLiteral(
"horline" );
356 return QStringLiteral(
"line" );
357 case Qt::BDiagPattern:
358 return QStringLiteral(
"slash" );
359 case Qt::FDiagPattern:
360 return QStringLiteral(
"backslash" );
363 case Qt::Dense1Pattern:
364 case Qt::Dense2Pattern:
365 case Qt::Dense3Pattern:
366 case Qt::Dense4Pattern:
367 case Qt::Dense5Pattern:
368 case Qt::Dense6Pattern:
369 case Qt::Dense7Pattern:
379 if (
str == QLatin1String(
"horline" ) )
return Qt::HorPattern;
380 if (
str == QLatin1String(
"line" ) )
return Qt::VerPattern;
381 if (
str == QLatin1String(
"cross" ) )
return Qt::CrossPattern;
382 if (
str == QLatin1String(
"slash" ) )
return Qt::BDiagPattern;
383 if (
str == QLatin1String(
"backshash" ) )
return Qt::FDiagPattern;
384 if (
str == QLatin1String(
"x" ) )
return Qt::DiagCrossPattern;
386 if (
str.startsWith( QLatin1String(
"brush://" ) ) )
394 const QString compareString =
string.trimmed();
398 if ( compareString.compare( QLatin1String(
"feature" ), Qt::CaseInsensitive ) == 0 )
400 else if ( compareString.compare( QLatin1String(
"viewport" ), Qt::CaseInsensitive ) == 0 )
410 switch ( coordinateReference )
413 return QStringLiteral(
"feature" );
415 return QStringLiteral(
"viewport" );
426 const QString s = value.toString().toLower().trimmed();
427 if ( s == QLatin1String(
"single" ) )
429 else if ( s == QLatin1String(
"reversed" ) )
431 else if ( s == QLatin1String(
"double" ) )
433 else if ( value.toInt() == 1 )
435 else if ( value.toInt() == 2 )
437 else if ( value.toInt( &intOk ) == 0 && intOk )
451 const QString s = value.toString().toLower().trimmed();
452 if ( s == QLatin1String(
"plain" ) )
454 else if ( s == QLatin1String(
"lefthalf" ) )
456 else if ( s == QLatin1String(
"righthalf" ) )
458 else if ( value.toInt() == 1 )
460 else if ( value.toInt() == 2 )
462 else if ( value.toInt( &intOk ) == 0 && intOk )
472 const QString compareString =
string.trimmed();
476 if ( compareString.compare( QLatin1String(
"no" ), Qt::CaseInsensitive ) == 0 )
478 else if ( compareString.compare( QLatin1String(
"shape" ), Qt::CaseInsensitive ) == 0 )
480 else if ( compareString.compare( QLatin1String(
"centroid_within" ), Qt::CaseInsensitive ) == 0 )
482 else if ( compareString.compare( QLatin1String(
"completely_within" ), Qt::CaseInsensitive ) == 0 )
495 return QStringLiteral(
"no" );
497 return QStringLiteral(
"shape" );
499 return QStringLiteral(
"centroid_within" );
501 return QStringLiteral(
"completely_within" );
508 const QString compareString =
string.trimmed();
512 if ( compareString.compare( QLatin1String(
"no" ), Qt::CaseInsensitive ) == 0 )
514 else if ( compareString.compare( QLatin1String(
"during_render" ), Qt::CaseInsensitive ) == 0 )
516 else if ( compareString.compare( QLatin1String(
"before_render" ), Qt::CaseInsensitive ) == 0 )
529 return QStringLiteral(
"no" );
531 return QStringLiteral(
"during_render" );
533 return QStringLiteral(
"before_render" );
545 QStringList lst =
str.split(
',' );
546 if ( lst.count() != 2 )
547 return QPointF( 0, 0 );
548 return QPointF( lst[0].toDouble(), lst[1].toDouble() );
559 if ( value.type() == QVariant::List )
561 const QVariantList list = value.toList();
562 if ( list.size() != 2 )
566 bool convertOk =
false;
567 const double x = list.at( 0 ).toDouble( &convertOk );
570 const double y = list.at( 1 ).toDouble( &convertOk );
575 return QPointF( x, y );
583 const QStringList list = value.toString().trimmed().split(
',' );
584 if ( list.count() != 2 )
586 bool convertOk =
false;
587 const double x = list.at( 0 ).toDouble( &convertOk );
590 const double y = list.at( 1 ).toDouble( &convertOk );
595 return QPointF( x, y );
609 QStringList lst =
string.split(
',' );
610 if ( lst.count() != 2 )
611 return QSizeF( 0, 0 );
612 return QSizeF( lst[0].toDouble(), lst[1].toDouble() );
623 if ( value.type() == QVariant::List )
625 const QVariantList list = value.toList();
626 if ( list.size() != 2 )
630 bool convertOk =
false;
631 const double x = list.at( 0 ).toDouble( &convertOk );
634 const double y = list.at( 1 ).toDouble( &convertOk );
639 return QSizeF( x, y );
647 const QStringList list = value.toString().trimmed().split(
',' );
648 if ( list.count() != 2 )
650 bool convertOk =
false;
651 const double x = list.at( 0 ).toDouble( &convertOk );
654 const double y = list.at( 1 ).toDouble( &convertOk );
659 return QSizeF( x, y );
680 if (
str.startsWith( QLatin1String(
"3x:" ) ) )
683 const QString chopped =
str.mid( 3 );
684 lst = chopped.split(
',' );
688 lst =
str.split(
',' );
690 if ( lst.count() < 2 )
693 double minScale = lst[0].toDouble();
695 minScale = minScale != 0 ? 1.0 / minScale : 0;
696 double maxScale = lst[1].toDouble();
698 maxScale = maxScale != 0 ? 1.0 / maxScale : 0;
700 if ( lst.count() < 6 )
720 *scaleFactor = 0.001;
721 return QStringLiteral(
"http://www.opengeospatial.org/se/units/metre" );
726 return QStringLiteral(
"http://www.opengeospatial.org/se/units/metre" );
733 *scaleFactor = 1 / 0.28;
742 if (
str == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
748 else if (
str == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
751 *scaleFactor = 0.3048;
766 QString vectorString;
767 QVector<qreal>::const_iterator it = v.constBegin();
768 for ( ; it != v.constEnd(); ++it )
770 if ( it != v.constBegin() )
772 vectorString.append(
';' );
774 vectorString.append( QString::number( *it ) );
781 QVector<qreal> resultVector;
783 const QStringList realList = s.split(
';' );
784 QStringList::const_iterator it = realList.constBegin();
785 for ( ; it != realList.constEnd(); ++it )
787 resultVector.append( it->toDouble() );
795 QString vectorString;
796 QVector<qreal>::const_iterator it = v.constBegin();
797 for ( ; it != v.constEnd(); ++it )
799 if ( it != v.constBegin() )
801 vectorString.append(
' ' );
803 vectorString.append( QString::number( *it ) );
810 QVector<qreal> resultVector;
812 const QStringList realList = s.split(
' ' );
813 QStringList::const_iterator it = realList.constBegin();
814 for ( ; it != realList.constEnd(); ++it )
816 resultVector.append( it->toDouble() );
824 QString encodedValue;
826 switch ( scaleMethod )
829 encodedValue = QStringLiteral(
"diameter" );
832 encodedValue = QStringLiteral(
"area" );
842 if (
str == QLatin1String(
"diameter" ) )
856 if ( s.compare( QLatin1String(
"Lighten" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Lighten;
857 if ( s.compare( QLatin1String(
"Screen" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Screen;
858 if ( s.compare( QLatin1String(
"Dodge" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorDodge;
859 if ( s.compare( QLatin1String(
"Addition" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Plus;
860 if ( s.compare( QLatin1String(
"Darken" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Darken;
861 if ( s.compare( QLatin1String(
"Multiply" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Multiply;
862 if ( s.compare( QLatin1String(
"Burn" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorBurn;
863 if ( s.compare( QLatin1String(
"Overlay" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Overlay;
864 if ( s.compare( QLatin1String(
"SoftLight" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_SoftLight;
865 if ( s.compare( QLatin1String(
"HardLight" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_HardLight;
866 if ( s.compare( QLatin1String(
"Difference" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Difference;
867 if ( s.compare( QLatin1String(
"Subtract" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Exclusion;
868 return QPainter::CompositionMode_SourceOver;
873 return QIcon(
symbolPreviewPixmap( symbol, size, padding,
nullptr,
false,
nullptr, shape, screen ) );
881 QPixmap pixmap( size * devicePixelRatio );
882 pixmap.setDevicePixelRatio( devicePixelRatio );
884 pixmap.fill( Qt::transparent );
886 painter.begin( &pixmap );
891 painter.setRenderHint( QPainter::Antialiasing );
892 painter.setRenderHint( QPainter::SmoothPixmapTransform );
902 size.setWidth( size.rwidth() - ( padding * 2 ) );
903 size.setHeight( size.rheight() - ( padding * 2 ) );
904 painter.translate( padding, padding );
914 std::unique_ptr<QgsSymbol> symbol_noDD( symbol->
clone( ) );
916 for (
const auto &layer : layers )
918 for (
int i = 0; i < layer->dataDefinedProperties().count(); ++i )
920 QgsProperty &prop = layer->dataDefinedProperties().property( i );
926 symbol_noDD->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape, screen );
930 std::unique_ptr<QgsSymbol> symbolClone( symbol->
clone( ) );
931 symbolClone->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape, screen );
945 maxBleed = layerMaxBleed > maxBleed ? layerMaxBleed : maxBleed;
955 painter.begin( &picture );
956 painter.setRenderHint( QPainter::Antialiasing );
964 QgsSymbolRenderContext symbolContext( renderContext, units, 1.0,
false, Qgis::SymbolRenderHints(),
nullptr );
966 switch ( parentSymbolType )
981 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
982 layerClone->drawPreviewIcon( symbolContext, size );
990 QPixmap pixmap( size * devicePixelRatio );
991 pixmap.setDevicePixelRatio( devicePixelRatio );
992 pixmap.fill( Qt::transparent );
994 painter.begin( &pixmap );
995 painter.setRenderHint( QPainter::Antialiasing );
1011 QgsSymbolRenderContext symbolContext( renderContext, u, 1.0,
false, Qgis::SymbolRenderHints(),
nullptr );
1013 switch ( parentSymbolType )
1028 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
1029 layerClone->drawPreviewIcon( symbolContext, size );
1031 return QIcon( pixmap );
1041 QPixmap pixmap( size );
1042 pixmap.fill( Qt::transparent );
1045 painter.begin( &pixmap );
1048 if ( drawTransparentBackground )
1049 drawStippledBackground( &painter, QRect( padding, padding, size.width() - padding * 2, size.height() - padding * 2 ) );
1053 switch ( direction )
1055 case Qt::Horizontal:
1057 for (
int i = 0; i < size.width(); i++ )
1059 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.width() ) );
1060 painter.setPen( pen );
1061 const int x = flipDirection ? size.width() - i - 1 : i;
1062 painter.drawLine( x, 0 + padding, x, size.height() - 1 - padding );
1069 for (
int i = 0; i < size.height(); i++ )
1071 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.height() ) );
1072 painter.setPen( pen );
1073 const int y = flipDirection ? size.height() - i - 1 : i;
1074 painter.drawLine( 0 + padding, y, size.width() - 1 - padding, y );
1087 uchar pixDataRGB[] = { 255, 255, 255, 255,
1092 const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
1094 const int width = ( rect.width() < rect.height() ) ?
1095 rect.width() / 2.5 : rect.height() / 2.5;
1096 const QPixmap pix = QPixmap::fromImage( img.scaled( width, width ) );
1099 brush.setTexture( pix );
1100 painter->fillRect( rect, brush );
1105 const qreal s = ( markerSize - 1 ) / 2.0;
1110 p.setPen( QColor( 50, 100, 120, 200 ) );
1111 p.setBrush( QColor( 200, 200, 210, 120 ) );
1112 p.drawEllipse( x - s, y - s, s * 2, s * 2 );
1115 p.setPen( QColor( 255, 0, 0 ) );
1116 p.drawLine( x - s, y + s, x + s, y - s );
1117 p.drawLine( x - s, y - s, x + s, y + s );
1129static QPolygonF makeOffsetGeometry(
const QgsPolylineXY &polyline )
1131 int i, pointCount = polyline.count();
1133 QPolygonF resultLine;
1134 resultLine.resize( pointCount );
1138 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1139 resultLine[i] = QPointF( tempPtr->
x(), tempPtr->
y() );
1143static QList<QPolygonF> makeOffsetGeometry(
const QgsPolygonXY &polygon )
1145 QList<QPolygonF> resultGeom;
1146 resultGeom.reserve( polygon.size() );
1147 for (
int ring = 0; ring < polygon.size(); ++ring )
1148 resultGeom.append( makeOffsetGeometry( polygon[ ring ] ) );
1154 QList<QPolygonF> resultLine;
1156 if ( polyline.count() < 2 )
1158 resultLine.append( polyline );
1162 unsigned int i, pointCount = polyline.count();
1165 QPointF *tempPtr = polyline.data();
1166 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1167 tempPolyline[i] =
QgsPointXY( tempPtr->rx(), tempPtr->ry() );
1170 if ( !tempGeometry.
isNull() )
1172 const int quadSegments = 0;
1173 const double miterLimit = 2.0;
1181 if ( !offsetGeom.
isNull() )
1183 tempGeometry = offsetGeom;
1188 resultLine.append( makeOffsetGeometry( line ) );
1193 resultLine.append( makeOffsetGeometry( tempGeometry.
asPolygon() ) );
1199 resultLine.reserve( tempMPolyline.count() );
1200 for (
int part = 0; part < tempMPolyline.count(); ++part )
1202 resultLine.append( makeOffsetGeometry( tempMPolyline[ part ] ) );
1209 resultLine.reserve( tempMPolygon.count() );
1210 for (
int part = 0; part < tempMPolygon.count(); ++part )
1212 resultLine.append( makeOffsetGeometry( tempMPolygon[ part ] ) );
1220 resultLine.append( polyline );
1229 if ( element.isNull() )
1233 QDomNode layerNode = element.firstChild();
1235 while ( !layerNode.isNull() )
1237 QDomElement e = layerNode.toElement();
1238 if ( !e.isNull() && e.tagName() != QLatin1String(
"data_defined_properties" ) )
1240 if ( e.tagName() != QLatin1String(
"layer" ) )
1249 const QDomElement s = e.firstChildElement( QStringLiteral(
"symbol" ) );
1252 std::unique_ptr< QgsSymbol > subSymbol(
loadSymbol( s, context ) );
1259 layers.append( layer );
1261 for (
int i = 0; i < subSymbol->symbolLayerCount(); ++i )
1263 layers.append( subSymbol->symbolLayer( i )->clone() );
1268 const bool res = layer->setSubSymbol( subSymbol.release() );
1271 QgsDebugError( QStringLiteral(
"symbol layer refused subsymbol: " ) + s.attribute(
"name" ) );
1273 layers.append( layer );
1278 layers.append( layer );
1283 layerNode = layerNode.nextSibling();
1286 if ( layers.isEmpty() )
1292 const QString symbolType = element.attribute( QStringLiteral(
"type" ) );
1295 if ( symbolType == QLatin1String(
"line" ) )
1297 else if ( symbolType == QLatin1String(
"fill" ) )
1299 else if ( symbolType == QLatin1String(
"marker" ) )
1307 if ( element.hasAttribute( QStringLiteral(
"outputUnit" ) ) )
1311 if ( element.hasAttribute( ( QStringLiteral(
"mapUnitScale" ) ) ) )
1314 const double oldMin = element.attribute( QStringLiteral(
"mapUnitMinScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1315 mapUnitScale.
minScale = oldMin != 0 ? 1.0 / oldMin : 0;
1316 const double oldMax = element.attribute( QStringLiteral(
"mapUnitMaxScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1317 mapUnitScale.
maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
1320 symbol->
setOpacity( element.attribute( QStringLiteral(
"alpha" ), QStringLiteral(
"1.0" ) ).toDouble() );
1321 symbol->
setClipFeaturesToExtent( element.attribute( QStringLiteral(
"clip_to_extent" ), QStringLiteral(
"1" ) ).toInt() );
1322 symbol->
setForceRHR( element.attribute( QStringLiteral(
"force_rhr" ), QStringLiteral(
"0" ) ).toInt() );
1323 Qgis::SymbolFlags flags;
1324 if ( element.attribute( QStringLiteral(
"renderer_should_use_levels" ), QStringLiteral(
"0" ) ).toInt() )
1331 const QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1332 if ( !ddProps.isNull() )
1342 const QString layerClass = element.attribute( QStringLiteral(
"class" ) );
1343 const bool locked = element.attribute( QStringLiteral(
"locked" ) ).toInt();
1344 const bool enabled = element.attribute( QStringLiteral(
"enabled" ), QStringLiteral(
"1" ) ).toInt();
1345 const int pass = element.attribute( QStringLiteral(
"pass" ) ).toInt();
1346 const QString
id = element.attribute( QStringLiteral(
"id" ) );
1347 const Qgis::SymbolLayerUserFlags userFlags =
qgsFlagKeysToValue( element.attribute( QStringLiteral(
"userFlags" ) ), Qgis::SymbolLayerUserFlags() );
1367 if ( !
id.isEmpty() )
1371 const QDomElement effectElem = element.firstChildElement( QStringLiteral(
"effect" ) );
1372 if ( !effectElem.isNull() )
1380 const QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1381 if ( !ddProps.isNull() )
1388 const QSet< int > oldKeys = prevProperties.
propertyKeys();
1389 for (
int key : oldKeys )
1410 return QStringLiteral(
"line" );
1412 return QStringLiteral(
"marker" );
1414 return QStringLiteral(
"fill" );
1423 QDomElement symEl = doc.createElement( QStringLiteral(
"symbol" ) );
1424 symEl.setAttribute( QStringLiteral(
"type" ), _nameForSymbolType( symbol->
type() ) );
1425 symEl.setAttribute( QStringLiteral(
"name" ), name );
1426 symEl.setAttribute( QStringLiteral(
"alpha" ), QString::number( symbol->
opacity() ) );
1427 symEl.setAttribute( QStringLiteral(
"clip_to_extent" ), symbol->
clipFeaturesToExtent() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1428 symEl.setAttribute( QStringLiteral(
"force_rhr" ), symbol->
forceRHR() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1430 symEl.setAttribute( QStringLiteral(
"renderer_should_use_levels" ), QStringLiteral(
"1" ) );
1432 symEl.setAttribute( QStringLiteral(
"is_animated" ), symbol->
animationSettings().
isAnimated() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1437 QDomElement ddProps = doc.createElement( QStringLiteral(
"data_defined_properties" ) );
1439 symEl.appendChild( ddProps );
1445 QDomElement layerEl = doc.createElement( QStringLiteral(
"layer" ) );
1446 layerEl.setAttribute( QStringLiteral(
"class" ), layer->
layerType() );
1447 layerEl.setAttribute( QStringLiteral(
"enabled" ), layer->
enabled() );
1448 layerEl.setAttribute( QStringLiteral(
"locked" ), layer->
isLocked() );
1449 layerEl.setAttribute( QStringLiteral(
"pass" ), layer->
renderingPass() );
1450 layerEl.setAttribute( QStringLiteral(
"id" ), layer->
id() );
1451 if ( layer->
userFlags() != Qgis::SymbolLayerUserFlags() )
1464 QDomElement ddProps = doc.createElement( QStringLiteral(
"data_defined_properties" ) );
1466 layerEl.appendChild( ddProps );
1470 const QString subname = QStringLiteral(
"@%1@%2" ).arg( name ).arg( i );
1471 const QDomElement subEl =
saveSymbol( subname, subSymbol, doc, context );
1472 layerEl.appendChild( subEl );
1474 symEl.appendChild( layerEl );
1482 QDomDocument doc( QStringLiteral(
"qgis-symbol-definition" ) );
1485 QTextStream stream( &props );
1486 symbolElem.save( stream, -1 );
1492 QList<QgsSymbolLayer *> &layers )
1496 if ( element.isNull() )
1501 const QString symbolizerName = element.localName();
1503 if ( symbolizerName == QLatin1String(
"PointSymbolizer" ) )
1506 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1507 if ( graphicElem.isNull() )
1509 QgsDebugError( QStringLiteral(
"Graphic element not found in PointSymbolizer" ) );
1545 if ( symbolizerName == QLatin1String(
"LineSymbolizer" ) )
1548 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1549 if ( strokeElem.isNull() )
1551 QgsDebugError( QStringLiteral(
"Stroke element not found in LineSymbolizer" ) );
1581 if ( symbolizerName == QLatin1String(
"PolygonSymbolizer" ) )
1584 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1585 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1586 if ( fillElem.isNull() && strokeElem.isNull() )
1588 QgsDebugError( QStringLiteral(
"neither Fill nor Stroke element not found in PolygonSymbolizer" ) );
1606 if ( l->
layerType() == QLatin1String(
"SimpleFill" ) || l->
layerType() == QLatin1String(
"SVGFill" ) )
1642 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1643 if ( fillElem.isNull() )
1645 QgsDebugError( QStringLiteral(
"Fill element not found" ) );
1667 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1668 if ( strokeElem.isNull() )
1670 QgsDebugError( QStringLiteral(
"Stroke element not found" ) );
1686 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1687 if ( graphicElem.isNull() )
1689 QgsDebugError( QStringLiteral(
"Graphic element not found" ) );
1714 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1715 if ( graphicElem.isNull() )
1718 const QDomElement externalGraphicElem = graphicElem.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
1719 if ( externalGraphicElem.isNull() )
1723 const QDomElement formatElem = externalGraphicElem.firstChildElement( QStringLiteral(
"Format" ) );
1724 if ( formatElem.isNull() )
1727 const QString elementFormat = formatElem.firstChild().nodeValue();
1728 if ( ! format.isEmpty() && elementFormat != format )
1730 QgsDebugMsgLevel(
"unsupported External Graphic format found: " + elementFormat, 4 );
1735 const QDomElement onlineResourceElem = externalGraphicElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1736 const QDomElement inlineContentElem = externalGraphicElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1737 if ( !onlineResourceElem.isNull() )
1742 else if ( !inlineContentElem.isNull() )
1755 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1756 if ( graphicElem.isNull() )
1759 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1760 if ( markElem.isNull() )
1763 const QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
1764 return !wellKnownNameElem.isNull();
1770 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1771 if ( graphicElem.isNull() )
1774 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1775 if ( markElem.isNull() )
1779 const QDomElement formatElem = markElem.firstChildElement( QStringLiteral(
"Format" ) );
1780 if ( formatElem.isNull() )
1783 const QString format = formatElem.firstChild().nodeValue();
1784 if ( format != QLatin1String(
"ttf" ) )
1786 QgsDebugError(
"unsupported Graphic Mark format found: " + format );
1791 const QDomElement onlineResourceElem = markElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1792 const QDomElement inlineContentElem = markElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1793 if ( !onlineResourceElem.isNull() )
1796 const QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
1797 if ( !markIndexElem.isNull() )
1800 else if ( !inlineContentElem.isNull() )
1815 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1816 if ( graphicElem.isNull() )
1820 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
1822 if ( it.key() == QLatin1String(
"widthHeightFactor" ) )
1833 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1834 if ( strokeElem.isNull() )
1837 QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral(
"GraphicStroke" ) );
1838 if ( graphicStrokeElem.isNull() )
1846 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1847 if ( fillElem.isNull() )
1850 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1851 if ( graphicFillElem.isNull() )
1854 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1855 if ( graphicElem.isNull() )
1861 QColor fillColor, strokeColor;
1862 double size, strokeWidth;
1863 Qt::PenStyle strokeStyle;
1864 if ( !
wellKnownMarkerFromSld( graphicElem, name, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
1867 if ( name != QLatin1String(
"horline" ) )
1875 const double angle = angleFunc.toDouble( &ok );
1881 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1882 if ( fillElem.isNull() )
1885 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1886 if ( graphicFillElem.isNull() )
1889 const QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1890 if ( graphicElem.isNull() )
1893 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1894 if ( markElem.isNull() )
1902 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1903 if ( fillElem.isNull() )
1906 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1907 if ( graphicFillElem.isNull() )
1915 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1916 if ( fillElem.isNull() )
1919 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1920 if ( graphicFillElem.isNull() )
1940 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1941 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1945 bool validFill =
false, validStroke =
false;
1950 Qt::BrushStyle fillStyle;
1952 if (
fillFromSld( fillElem, fillStyle, fillColor ) )
1958 Qt::PenStyle strokeStyle;
1959 double strokeWidth = 1.0, dashOffset = 0.0;
1960 QVector<qreal> customDashPattern;
1962 if (
lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth,
1963 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
1966 if ( validFill || validStroke )
1969 map[QStringLiteral(
"name" )] = QStringLiteral(
"square" );
1970 map[QStringLiteral(
"color" )] =
encodeColor( validFill ? fillColor : Qt::transparent );
1971 map[QStringLiteral(
"color_border" )] =
encodeColor( validStroke ? strokeColor : Qt::transparent );
1972 map[QStringLiteral(
"size" )] = QString::number( 6 );
1973 map[QStringLiteral(
"angle" )] = QString::number( 0 );
1974 map[QStringLiteral(
"offset" )] =
encodePoint( QPointF( 0, 0 ) );
1981 bool validFill =
false, validStroke =
false;
1984 QString name, format;
1986 QColor fillColor, strokeColor;
1987 double strokeWidth = 1.0, size = 0.0, angle = 0.0;
1991 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1992 if ( !graphicFillElem.isNull() )
1995 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1996 if ( !graphicElem.isNull() )
2002 const QDomElement graphicChildElem = graphicElem.firstChildElement();
2003 while ( !graphicChildElem.isNull() )
2005 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2008 const QDomElement wellKnownNameElem = graphicChildElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
2009 if ( !wellKnownNameElem.isNull() )
2011 name = wellKnownNameElem.firstChild().nodeValue();
2017 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) || graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2020 const QDomElement formatElem = graphicChildElem.firstChildElement( QStringLiteral(
"Format" ) );
2021 if ( formatElem.isNull() )
2024 format = formatElem.firstChild().nodeValue();
2028 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) && format != QLatin1String(
"image/svg+xml" ) )
2033 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format != QLatin1String(
"ttf" ) )
2037 const QDomElement onlineResourceElem = graphicChildElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
2038 const QDomElement inlineContentElem = graphicChildElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
2040 if ( !onlineResourceElem.isNull() )
2042 name = onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) );
2044 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format == QLatin1String(
"ttf" ) )
2047 if ( name.startsWith( QLatin1String(
"ttf://" ) ) )
2048 name = name.mid( 6 );
2051 const QDomElement markIndexElem = graphicChildElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
2052 if ( markIndexElem.isNull() )
2056 const int v = markIndexElem.firstChild().nodeValue().toInt( &ok );
2067 else if ( !inlineContentElem.isNull() )
2077 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2079 name = QStringLiteral(
"square" );
2086 if ( found && graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2093 Qt::BrushStyle markFillStyle;
2095 QDomElement markFillElem = graphicChildElem.firstChildElement( QStringLiteral(
"Fill" ) );
2096 if (
fillFromSld( markFillElem, markFillStyle, fillColor ) )
2101 Qt::PenStyle strokeStyle;
2102 double strokeWidth = 1.0, dashOffset = 0.0;
2103 QVector<qreal> customDashPattern;
2105 QDomElement markStrokeElem = graphicChildElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2106 if (
lineFromSld( markStrokeElem, strokeStyle, strokeColor, strokeWidth,
2107 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2114 const QDomElement opacityElem = graphicElem.firstChildElement( QStringLiteral(
"Opacity" ) );
2115 if ( !opacityElem.isNull() )
2116 fillColor.setAlpha(
decodeSldAlpha( opacityElem.firstChild().nodeValue() ) );
2118 const QDomElement sizeElem = graphicElem.firstChildElement( QStringLiteral(
"Size" ) );
2119 if ( !sizeElem.isNull() )
2122 const double v = sizeElem.firstChild().nodeValue().toDouble( &ok );
2131 const double v = angleFunc.toDouble( &ok );
2141 if ( validFill || validStroke )
2143 if ( format == QLatin1String(
"image/svg+xml" ) )
2146 map[QStringLiteral(
"name" )] = name;
2147 map[QStringLiteral(
"fill" )] = fillColor.name();
2148 map[QStringLiteral(
"outline" )] = strokeColor.name();
2149 map[QStringLiteral(
"outline-width" )] = QString::number( strokeWidth );
2151 map[QStringLiteral(
"size" )] = QString::number( size );
2153 map[QStringLiteral(
"angle" )] = QString::number( angle );
2154 if ( !offset.isNull() )
2155 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
2158 else if ( format == QLatin1String(
"ttf" ) )
2161 map[QStringLiteral(
"font" )] = name;
2162 map[QStringLiteral(
"chr" )] = markIndex;
2163 map[QStringLiteral(
"color" )] =
encodeColor( validFill ? fillColor : Qt::transparent );
2165 map[QStringLiteral(
"size" )] = QString::number( size );
2167 map[QStringLiteral(
"angle" )] = QString::number( angle );
2168 if ( !offset.isNull() )
2169 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
2175 if ( layers.isEmpty() )
2178 layerList << layers;
2185 QString patternName;
2186 switch ( brushStyle )
2191 case Qt::SolidPattern:
2192 if ( color.isValid() )
2195 if ( color.alpha() < 255 )
2200 case Qt::CrossPattern:
2201 case Qt::DiagCrossPattern:
2202 case Qt::HorPattern:
2203 case Qt::VerPattern:
2204 case Qt::BDiagPattern:
2205 case Qt::FDiagPattern:
2206 case Qt::Dense1Pattern:
2207 case Qt::Dense2Pattern:
2208 case Qt::Dense3Pattern:
2209 case Qt::Dense4Pattern:
2210 case Qt::Dense5Pattern:
2211 case Qt::Dense6Pattern:
2212 case Qt::Dense7Pattern:
2217 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( brushStyle ) ) );
2221 QDomElement graphicFillElem = doc.createElement( QStringLiteral(
"se:GraphicFill" ) );
2222 element.appendChild( graphicFillElem );
2224 QDomElement graphicElem = doc.createElement( QStringLiteral(
"se:Graphic" ) );
2225 graphicFillElem.appendChild( graphicElem );
2227 const QColor fillColor = patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
2228 const QColor strokeColor = !patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
2231 wellKnownMarkerToSld( doc, graphicElem, patternName, fillColor, strokeColor, Qt::SolidLine, -1, -1 );
2238 brushStyle = Qt::SolidPattern;
2239 color = QColor( 128, 128, 128 );
2241 if ( element.isNull() )
2243 brushStyle = Qt::NoBrush;
2248 const QDomElement graphicFillElem = element.firstChildElement( QStringLiteral(
"GraphicFill" ) );
2250 if ( graphicFillElem.isNull() )
2253 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2255 QgsDebugMsgLevel( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ), 2 );
2257 if ( it.key() == QLatin1String(
"fill" ) )
2258 color = QColor( it.value() );
2259 else if ( it.key() == QLatin1String(
"fill-opacity" ) )
2265 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
2266 if ( graphicElem.isNull() )
2269 QString patternName = QStringLiteral(
"square" );
2270 QColor fillColor, strokeColor;
2271 double strokeWidth, size;
2272 Qt::PenStyle strokeStyle;
2273 if ( !
wellKnownMarkerFromSld( graphicElem, patternName, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
2277 if ( brushStyle == Qt::NoBrush )
2280 const QColor
c = patternName.startsWith( QLatin1String(
"brush://" ) ) ? fillColor : strokeColor;
2289 Qt::PenStyle penStyle,
const QColor &color,
double width,
2290 const Qt::PenJoinStyle *penJoinStyle,
const Qt::PenCapStyle *penCapStyle,
2291 const QVector<qreal> *customDashPattern,
double dashOffset )
2293 QVector<qreal> dashPattern;
2294 const QVector<qreal> *pattern = &dashPattern;
2296 if ( penStyle == Qt::CustomDashLine && !customDashPattern )
2298 element.appendChild( doc.createComment( QStringLiteral(
"WARNING: Custom dash pattern required but not provided. Using default dash pattern." ) ) );
2299 penStyle = Qt::DashLine;
2311 dashPattern.push_back( 4.0 );
2312 dashPattern.push_back( 2.0 );
2315 dashPattern.push_back( 1.0 );
2316 dashPattern.push_back( 2.0 );
2318 case Qt::DashDotLine:
2319 dashPattern.push_back( 4.0 );
2320 dashPattern.push_back( 2.0 );
2321 dashPattern.push_back( 1.0 );
2322 dashPattern.push_back( 2.0 );
2324 case Qt::DashDotDotLine:
2325 dashPattern.push_back( 4.0 );
2326 dashPattern.push_back( 2.0 );
2327 dashPattern.push_back( 1.0 );
2328 dashPattern.push_back( 2.0 );
2329 dashPattern.push_back( 1.0 );
2330 dashPattern.push_back( 2.0 );
2333 case Qt::CustomDashLine:
2334 Q_ASSERT( customDashPattern );
2335 pattern = customDashPattern;
2339 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( penStyle ) ) );
2343 if ( color.isValid() )
2346 if ( color.alpha() < 255 )
2353 else if ( width == 0 )
2363 if ( !pattern->isEmpty() )
2373 Qt::PenStyle &penStyle, QColor &color,
double &width,
2374 Qt::PenJoinStyle *penJoinStyle, Qt::PenCapStyle *penCapStyle,
2375 QVector<qreal> *customDashPattern,
double *dashOffset )
2379 penStyle = Qt::SolidLine;
2380 color = QColor( 0, 0, 0 );
2383 *penJoinStyle = Qt::BevelJoin;
2385 *penCapStyle = Qt::SquareCap;
2386 if ( customDashPattern )
2387 customDashPattern->clear();
2391 if ( element.isNull() )
2393 penStyle = Qt::NoPen;
2399 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2401 QgsDebugMsgLevel( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ), 2 );
2403 if ( it.key() == QLatin1String(
"stroke" ) )
2405 color = QColor( it.value() );
2407 else if ( it.key() == QLatin1String(
"stroke-opacity" ) )
2411 else if ( it.key() == QLatin1String(
"stroke-width" ) )
2414 const double w = it.value().toDouble( &ok );
2418 else if ( it.key() == QLatin1String(
"stroke-linejoin" ) && penJoinStyle )
2422 else if ( it.key() == QLatin1String(
"stroke-linecap" ) && penCapStyle )
2426 else if ( it.key() == QLatin1String(
"stroke-dasharray" ) )
2429 if ( !dashPattern.isEmpty() )
2433 bool dashPatternFound =
false;
2435 if ( dashPattern.count() == 2 )
2437 if ( dashPattern.at( 0 ) == 4.0 &&
2438 dashPattern.at( 1 ) == 2.0 )
2440 penStyle = Qt::DashLine;
2441 dashPatternFound =
true;
2443 else if ( dashPattern.at( 0 ) == 1.0 &&
2444 dashPattern.at( 1 ) == 2.0 )
2446 penStyle = Qt::DotLine;
2447 dashPatternFound =
true;
2450 else if ( dashPattern.count() == 4 )
2452 if ( dashPattern.at( 0 ) == 4.0 &&
2453 dashPattern.at( 1 ) == 2.0 &&
2454 dashPattern.at( 2 ) == 1.0 &&
2455 dashPattern.at( 3 ) == 2.0 )
2457 penStyle = Qt::DashDotLine;
2458 dashPatternFound =
true;
2461 else if ( dashPattern.count() == 6 )
2463 if ( dashPattern.at( 0 ) == 4.0 &&
2464 dashPattern.at( 1 ) == 2.0 &&
2465 dashPattern.at( 2 ) == 1.0 &&
2466 dashPattern.at( 3 ) == 2.0 &&
2467 dashPattern.at( 4 ) == 1.0 &&
2468 dashPattern.at( 5 ) == 2.0 )
2470 penStyle = Qt::DashDotDotLine;
2471 dashPatternFound =
true;
2476 if ( !dashPatternFound )
2478 if ( customDashPattern )
2480 penStyle = Qt::CustomDashLine;
2481 *customDashPattern = dashPattern;
2485 QgsDebugMsgLevel( QStringLiteral(
"custom dash pattern required but not provided. Using default dash pattern." ), 2 );
2486 penStyle = Qt::DashLine;
2491 else if ( it.key() == QLatin1String(
"stroke-dashoffset" ) && dashOffset )
2494 const double d = it.value().toDouble( &ok );
2504 const QString &path,
const QString &mime,
2505 const QColor &color,
double size )
2507 QDomElement externalGraphicElem = doc.createElement( QStringLiteral(
"se:ExternalGraphic" ) );
2508 element.appendChild( externalGraphicElem );
2517 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2519 element.appendChild( sizeElem );
2524 const QString &path,
const QColor &fillColor,
double size,
const QColor &strokeColor,
double strokeWidth )
2531 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Parametric SVG" ) ) );
2532 const QString parametricPath =
getSvgParametricPath( path, fillColor, strokeColor, strokeWidth );
2535 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Plain SVG fallback, no parameters" ) ) );
2538 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Well known marker fallback" ) ) );
2544 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2546 graphicElem.appendChild( sizeElem );
2554 if ( fillColor.isValid() )
2556 url.addQueryItem( QStringLiteral(
"fill" ), fillColor.name() );
2557 url.addQueryItem( QStringLiteral(
"fill-opacity" ),
encodeSldAlpha( fillColor.alpha() ) );
2561 url.addQueryItem( QStringLiteral(
"fill" ), QStringLiteral(
"#000000" ) );
2562 url.addQueryItem( QStringLiteral(
"fill-opacity" ), QStringLiteral(
"1" ) );
2564 if ( strokeColor.isValid() )
2566 url.addQueryItem( QStringLiteral(
"outline" ), strokeColor.name() );
2567 url.addQueryItem( QStringLiteral(
"outline-opacity" ),
encodeSldAlpha( strokeColor.alpha() ) );
2571 url.addQueryItem( QStringLiteral(
"outline" ), QStringLiteral(
"#000000" ) );
2572 url.addQueryItem( QStringLiteral(
"outline-opacity" ), QStringLiteral(
"1" ) );
2574 url.addQueryItem( QStringLiteral(
"outline-width" ), QString::number( strokeWidth ) );
2575 const QString params = url.toString( QUrl::FullyEncoded );
2576 if ( params.isEmpty() )
2582 return basePath +
"?" + params;
2587 QString &path, QString &mime,
2588 QColor &color,
double &size )
2593 QDomElement externalGraphicElem = element.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
2594 if ( externalGraphicElem.isNull() )
2599 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2600 if ( !sizeElem.isNull() )
2603 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2612 const QString &path,
const QString &format,
int *markIndex,
2613 const QColor &color,
double size )
2615 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2616 element.appendChild( markElem );
2622 QDomElement markIndexElem = doc.createElement( QStringLiteral(
"se:MarkIndex" ) );
2623 markIndexElem.appendChild( doc.createTextNode( QString::number( *markIndex ) ) );
2624 markElem.appendChild( markIndexElem );
2628 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2629 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2630 markElem.appendChild( fillElem );
2635 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2637 element.appendChild( sizeElem );
2642 QString &path, QString &format,
int &markIndex,
2643 QColor &color,
double &size )
2651 QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2652 if ( markElem.isNull() )
2657 const QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
2658 if ( !markIndexElem.isNull() )
2661 const int i = markIndexElem.firstChild().nodeValue().toInt( &ok );
2667 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2668 Qt::BrushStyle b = Qt::SolidPattern;
2673 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2674 if ( !sizeElem.isNull() )
2677 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2686 const QString &name,
const QColor &color,
const QColor &strokeColor, Qt::PenStyle strokeStyle,
2687 double strokeWidth,
double size )
2689 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2690 element.appendChild( markElem );
2692 QDomElement wellKnownNameElem = doc.createElement( QStringLiteral(
"se:WellKnownName" ) );
2693 wellKnownNameElem.appendChild( doc.createTextNode( name ) );
2694 markElem.appendChild( wellKnownNameElem );
2697 if ( color.isValid() )
2699 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2700 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2701 markElem.appendChild( fillElem );
2705 if ( strokeColor.isValid() )
2707 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
2708 lineToSld( doc, strokeElem, strokeStyle, strokeColor, strokeWidth );
2709 markElem.appendChild( strokeElem );
2715 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2717 element.appendChild( sizeElem );
2722 QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle,
2723 double &strokeWidth,
double &size )
2727 name = QStringLiteral(
"square" );
2729 strokeColor = QColor( 0, 0, 0 );
2733 const QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2734 if ( markElem.isNull() )
2737 const QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
2738 if ( !wellKnownNameElem.isNull() )
2740 name = wellKnownNameElem.firstChild().nodeValue();
2745 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2746 Qt::BrushStyle b = Qt::SolidPattern;
2751 QDomElement strokeElem = markElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2752 lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth );
2756 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2757 if ( !sizeElem.isNull() )
2760 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2770 if ( !rotationFunc.isEmpty() )
2772 QDomElement rotationElem = doc.createElement( QStringLiteral(
"se:Rotation" ) );
2774 element.appendChild( rotationElem );
2780 QDomElement rotationElem = element.firstChildElement( QStringLiteral(
"Rotation" ) );
2781 if ( !rotationElem.isNull() )
2791 if ( !alphaFunc.isEmpty() )
2793 QDomElement opacityElem = doc.createElement( QStringLiteral(
"se:Opacity" ) );
2795 element.appendChild( opacityElem );
2801 QDomElement opacityElem = element.firstChildElement( QStringLiteral(
"Opacity" ) );
2802 if ( !opacityElem.isNull() )
2811 if ( offset.isNull() )
2814 QDomElement displacementElem = doc.createElement( QStringLiteral(
"se:Displacement" ) );
2815 element.appendChild( displacementElem );
2817 QDomElement dispXElem = doc.createElement( QStringLiteral(
"se:DisplacementX" ) );
2818 dispXElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.x(), 2 ) ) );
2820 QDomElement dispYElem = doc.createElement( QStringLiteral(
"se:DisplacementY" ) );
2821 dispYElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.y(), 2 ) ) );
2823 displacementElem.appendChild( dispXElem );
2824 displacementElem.appendChild( dispYElem );
2831 QDomElement anchorElem = doc.createElement( QStringLiteral(
"se:AnchorPoint" ) );
2832 element.appendChild( anchorElem );
2834 QDomElement anchorXElem = doc.createElement( QStringLiteral(
"se:AnchorPointX" ) );
2835 anchorXElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.x() ) ) );
2837 QDomElement anchorYElem = doc.createElement( QStringLiteral(
"se:AnchorPointY" ) );
2838 anchorYElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.y() ) ) );
2840 anchorElem.appendChild( anchorXElem );
2841 anchorElem.appendChild( anchorYElem );
2846 offset = QPointF( 0, 0 );
2848 const QDomElement displacementElem = element.firstChildElement( QStringLiteral(
"Displacement" ) );
2849 if ( displacementElem.isNull() )
2852 const QDomElement dispXElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementX" ) );
2853 if ( !dispXElem.isNull() )
2856 const double offsetX = dispXElem.firstChild().nodeValue().toDouble( &ok );
2858 offset.setX( offsetX );
2861 const QDomElement dispYElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementY" ) );
2862 if ( !dispYElem.isNull() )
2865 const double offsetY = dispYElem.firstChild().nodeValue().toDouble( &ok );
2867 offset.setY( offsetY );
2874 const QString &label,
const QFont &font,
2875 const QColor &color,
double size )
2877 QDomElement labelElem = doc.createElement( QStringLiteral(
"se:Label" ) );
2878 labelElem.appendChild( doc.createTextNode( label ) );
2879 element.appendChild( labelElem );
2881 QDomElement fontElem = doc.createElement( QStringLiteral(
"se:Font" ) );
2882 element.appendChild( fontElem );
2886 fontElem.appendChild( createSldParameterElement( doc,
"font-style",
encodeSldFontStyle( font.style() ) ) );
2887 fontElem.appendChild( createSldParameterElement( doc,
"font-weight",
encodeSldFontWeight( font.weight() ) ) );
2892 if ( color.isValid() )
2894 QDomElement fillElem = doc.createElement( QStringLiteral(
"Fill" ) );
2895 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2896 element.appendChild( fillElem );
2901 Qt::PenJoinStyle joinStyle,
2902 Qt::PenCapStyle capStyle,
2904 const QVector<qreal> *dashPattern )
2907 penStyle.append(
"PEN(" );
2908 penStyle.append(
"c:" );
2909 penStyle.append(
c.name() );
2910 penStyle.append(
",w:" );
2912 penStyle.append( QString::number( width * mmScaleFactor ) );
2913 penStyle.append(
"mm" );
2916 if ( dashPattern && !dashPattern->isEmpty() )
2918 penStyle.append(
",p:\"" );
2919 QVector<qreal>::const_iterator pIt = dashPattern->constBegin();
2920 for ( ; pIt != dashPattern->constEnd(); ++pIt )
2922 if ( pIt != dashPattern->constBegin() )
2924 penStyle.append(
' ' );
2926 penStyle.append( QString::number( *pIt * mapUnitScaleFactor ) );
2927 penStyle.append(
'g' );
2929 penStyle.append(
'\"' );
2933 penStyle.append(
",cap:" );
2937 penStyle.append(
'p' );
2940 penStyle.append(
'r' );
2944 penStyle.append(
'b' );
2948 penStyle.append(
",j:" );
2949 switch ( joinStyle )
2952 penStyle.append(
'b' );
2955 penStyle.append(
'r' );
2959 penStyle.append(
'm' );
2965 penStyle.append(
",dp:" );
2966 penStyle.append( QString::number( offset * mapUnitScaleFactor ) );
2967 penStyle.append(
'g' );
2970 penStyle.append(
')' );
2977 brushStyle.append(
"BRUSH(" );
2978 brushStyle.append(
"fc:" );
2979 brushStyle.append( fillColor.name() );
2980 brushStyle.append(
')' );
2986 if ( geomFunc.isEmpty() )
2989 QDomElement geometryElem = doc.createElement( QStringLiteral(
"Geometry" ) );
2990 element.appendChild( geometryElem );
3020 QDomElement geometryElem = element.firstChildElement( QStringLiteral(
"Geometry" ) );
3021 if ( geometryElem.isNull() )
3033 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " + function ) );
3037 if ( !filterElem.isNull() )
3038 element.appendChild( filterElem );
3046 if ( function == QLatin1String(
"ELSE" ) )
3049 element.appendChild( filterElem );
3058 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " + function ) );
3062 if ( !filterElem.isNull() )
3063 element.appendChild( filterElem );
3071 QDomElement elem = element;
3072 if ( element.tagName() != QLatin1String(
"Filter" ) )
3074 const QDomNodeList filterNodes = element.elementsByTagName( QStringLiteral(
"Filter" ) );
3075 if ( !filterNodes.isEmpty() )
3077 elem = filterNodes.at( 0 ).toElement();
3081 if ( elem.isNull() )
3106 const QString &path,
const QString &format )
3110 QDomElement onlineResourceElem = doc.createElement( QStringLiteral(
"se:OnlineResource" ) );
3111 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
3112 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:href" ), url );
3113 element.appendChild( onlineResourceElem );
3115 QDomElement formatElem = doc.createElement( QStringLiteral(
"se:Format" ) );
3116 formatElem.appendChild( doc.createTextNode( format ) );
3117 element.appendChild( formatElem );
3124 const QDomElement onlineResourceElem = element.firstChildElement( QStringLiteral(
"OnlineResource" ) );
3125 if ( onlineResourceElem.isNull() )
3128 path = QUrl::fromPercentEncoding( onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) ).toUtf8() );
3130 const QDomElement formatElem = element.firstChildElement( QStringLiteral(
"Format" ) );
3131 if ( formatElem.isNull() )
3134 format = formatElem.firstChild().nodeValue();
3141 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:SvgParameter" ) );
3142 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
3143 nodeElem.appendChild( doc.createTextNode( value ) );
3152 QDomElement paramElem = element.firstChildElement();
3153 while ( !paramElem.isNull() )
3155 if ( paramElem.localName() == QLatin1String(
"SvgParameter" ) || paramElem.localName() == QLatin1String(
"CssParameter" ) )
3157 const QString name = paramElem.attribute( QStringLiteral(
"name" ) );
3158 if ( paramElem.firstChild().nodeType() == QDomNode::TextNode )
3160 value = paramElem.firstChild().nodeValue();
3164 if ( paramElem.firstChild().nodeType() == QDomNode::ElementNode &&
3165 paramElem.firstChild().localName() == QLatin1String(
"Literal" ) )
3168 value = paramElem.firstChild().firstChild().nodeValue();
3172 QgsDebugError( QStringLiteral(
"unexpected child of %1" ).arg( paramElem.localName() ) );
3176 if ( !name.isEmpty() && !value.isEmpty() )
3177 params[ name ] = value;
3180 paramElem = paramElem.nextSiblingElement();
3188 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:VendorOption" ) );
3189 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
3190 nodeElem.appendChild( doc.createTextNode( value ) );
3198 QDomElement paramElem = element.firstChildElement( QStringLiteral(
"VendorOption" ) );
3199 while ( !paramElem.isNull() )
3201 const QString name = paramElem.attribute( QStringLiteral(
"name" ) );
3202 const QString value = paramElem.firstChild().nodeValue();
3204 if ( !name.isEmpty() && !value.isEmpty() )
3205 params[ name ] = value;
3207 paramElem = paramElem.nextSiblingElement( QStringLiteral(
"VendorOption" ) );
3217 if ( newSymbols.type() == QVariant::Map )
3219 return newSymbols.toMap();
3226 QDomElement e = element.firstChildElement();
3227 while ( !e.isNull() )
3229 if ( e.tagName() == QLatin1String(
"prop" ) )
3231 const QString propKey = e.attribute( QStringLiteral(
"k" ) );
3232 const QString propValue = e.attribute( QStringLiteral(
"v" ) );
3233 props[propKey] = propValue;
3235 e = e.nextSiblingElement();
3252 QDomElement e = element.firstChildElement();
3254 while ( !e.isNull() )
3256 if ( e.tagName() == QLatin1String(
"symbol" ) )
3260 symbols.insert( e.attribute( QStringLiteral(
"name" ) ), symbol );
3266 e = e.nextSiblingElement();
3273 QStringList subsymbols;
3275 for ( QMap<QString, QgsSymbol *>::iterator it = symbols.begin(); it != symbols.end(); ++it )
3277 if ( it.key()[0] !=
'@' )
3281 subsymbols.append( it.key() );
3283 QStringList parts = it.key().split(
'@' );
3284 if ( parts.count() < 3 )
3286 QgsDebugError(
"found subsymbol with invalid name: " + it.key() );
3290 const QString symname = parts[1];
3291 const int symlayer = parts[2].toInt();
3293 if ( !symbols.contains( symname ) )
3295 QgsDebugError(
"subsymbol references invalid symbol: " + symname );
3303 QgsDebugError(
"subsymbol references invalid symbol layer: " + QString::number( symlayer ) );
3312 QgsDebugError(
"symbol layer refused subsymbol: " + it.key() );
3319 for (
int i = 0; i < subsymbols.count(); i++ )
3320 symbols.take( subsymbols[i] );
3327 QDomElement symbolsElem = doc.createElement( tagName );
3330 for ( QMap<QString, QgsSymbol *>::iterator its = symbols.begin(); its != symbols.end(); ++its )
3332 const QDomElement symEl =
saveSymbol( its.key(), its.value(), doc, context );
3333 symbolsElem.appendChild( symEl );
3341 qDeleteAll( symbols );
3350 std::unique_ptr< QMimeData >mimeData(
new QMimeData );
3352 QDomDocument symbolDoc;
3354 symbolDoc.appendChild( symbolElem );
3355 mimeData->setText( symbolDoc.toString() );
3358 mimeData->setColorData( symbol->
color() );
3360 return mimeData.release();
3368 const QString text = data->text();
3369 if ( !text.isEmpty() )
3374 if ( doc.setContent( text ) )
3376 elem = doc.documentElement();
3378 if ( elem.nodeName() != QLatin1String(
"symbol" ) )
3379 elem = elem.firstChildElement( QStringLiteral(
"symbol" ) );
3390 const QString rampType = element.attribute( QStringLiteral(
"type" ) );
3415 QDomElement rampEl = doc.createElement( QStringLiteral(
"colorramp" ) );
3416 rampEl.setAttribute( QStringLiteral(
"type" ), ramp->
type() );
3417 rampEl.setAttribute( QStringLiteral(
"name" ), name );
3425 QVariantMap rampMap;
3427 rampMap.insert( QStringLiteral(
"type" ), ramp->
type() );
3428 rampMap.insert( QStringLiteral(
"name" ), name );
3430 const QVariantMap properties = ramp->
properties();
3432 QVariantMap propertyMap;
3433 for (
auto property = properties.constBegin();
property != properties.constEnd(); ++property )
3435 propertyMap.insert( property.key(),
property.value() );
3438 rampMap.insert( QStringLiteral(
"properties" ), propertyMap );
3444 const QVariantMap rampMap = value.toMap();
3446 const QString rampType = rampMap.
value( QStringLiteral(
"type" ) ).toString();
3449 const QVariantMap propertyMap = rampMap.value( QStringLiteral(
"properties" ) ).toMap();
3452 for (
auto property = propertyMap.constBegin();
property != propertyMap.constEnd(); ++property )
3454 props.insert( property.key(),
property.value().toString() );
3476 if ( !color.isValid() )
3483 return color.name();
3488 QList<QColor> colors;
3491 const thread_local QRegularExpression sepCommaSpaceRegExp(
"(,|\\s)" );
3492 QStringList components = colorStr.simplified().split( sepCommaSpaceRegExp );
3493 QStringList::iterator it = components.begin();
3494 for ( ; it != components.end(); ++it )
3496 const QColor result =
parseColor( *it,
true );
3497 if ( result.isValid() )
3502 if ( colors.length() > 0 )
3508 const thread_local QRegularExpression sepCommaRegExp(
"(,|\n)" );
3509 components = colorStr.split( sepCommaRegExp );
3510 it = components.begin();
3511 for ( ; it != components.end(); ++it )
3513 const QColor result =
parseColor( *it,
true );
3514 if ( result.isValid() )
3519 if ( colors.length() > 0 )
3525 components = colorStr.simplified().split( QString(
' ' ) );
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.split(
'\n' );
3542 it = components.begin();
3543 for ( ; it != components.end(); ++it )
3545 const QColor result =
parseColor( *it,
true );
3546 if ( result.isValid() )
3559 QMimeData *mimeData =
new QMimeData;
3560 mimeData->setColorData( QVariant( color ) );
3561 mimeData->setText( color.name() );
3568 if ( mimeData->hasColor() )
3570 QColor mimeColor = mimeData->colorData().value<QColor>();
3571 if ( mimeColor.isValid() )
3579 if ( mimeData->hasText() )
3583 if ( textColor.isValid() )
3598 if ( data->hasFormat( QStringLiteral(
"text/xml" ) ) )
3601 const QByteArray encodedData = data->data( QStringLiteral(
"text/xml" ) );
3602 QDomDocument xmlDoc;
3603 xmlDoc.setContent( encodedData );
3605 const QDomElement dragDataElem = xmlDoc.documentElement();
3606 if ( dragDataElem.tagName() == QLatin1String(
"ColorSchemeModelDragData" ) )
3608 const QDomNodeList nodeList = dragDataElem.childNodes();
3609 const int nChildNodes = nodeList.size();
3610 QDomElement currentElem;
3612 for (
int i = 0; i < nChildNodes; ++i )
3614 currentElem = nodeList.at( i ).toElement();
3615 if ( currentElem.isNull() )
3620 QPair< QColor, QString> namedColor;
3622 namedColor.second = currentElem.attribute( QStringLiteral(
"label" ), QString() );
3624 mimeColors << namedColor;
3629 if ( mimeColors.length() == 0 && data->hasFormat( QStringLiteral(
"application/x-colorobject-list" ) ) )
3632 const QByteArray encodedData = data->data( QStringLiteral(
"application/x-colorobject-list" ) );
3633 QDomDocument xmlDoc;
3634 xmlDoc.setContent( encodedData );
3636 const QDomNodeList colorsNodes = xmlDoc.elementsByTagName( QStringLiteral(
"colors" ) );
3637 if ( colorsNodes.length() > 0 )
3639 const QDomElement colorsElem = colorsNodes.at( 0 ).toElement();
3640 const QDomNodeList colorNodeList = colorsElem.childNodes();
3641 const int nChildNodes = colorNodeList.size();
3642 QDomElement currentElem;
3644 for (
int i = 0; i < nChildNodes; ++i )
3647 currentElem = colorNodeList.at( i ).toElement();
3648 if ( currentElem.isNull() )
3653 const QDomNodeList colorNodes = currentElem.elementsByTagName( QStringLiteral(
"color" ) );
3654 const QDomNodeList nameNodes = currentElem.elementsByTagName( QStringLiteral(
"name" ) );
3656 if ( colorNodes.length() > 0 )
3658 const QDomElement colorElem = colorNodes.at( 0 ).toElement();
3660 const QStringList colorParts = colorElem.text().simplified().split(
' ' );
3661 if ( colorParts.length() < 3 )
3666 const int red = colorParts.at( 0 ).toDouble() * 255;
3667 const int green = colorParts.at( 1 ).toDouble() * 255;
3668 const int blue = colorParts.at( 2 ).toDouble() * 255;
3669 QPair< QColor, QString> namedColor;
3670 namedColor.first = QColor( red, green, blue );
3671 if ( nameNodes.length() > 0 )
3673 const QDomElement nameElem = nameNodes.at( 0 ).toElement();
3674 namedColor.second = nameElem.text();
3676 mimeColors << namedColor;
3682 if ( mimeColors.length() == 0 && data->hasText() )
3686 QList< QColor >::iterator it = parsedColors.begin();
3687 for ( ; it != parsedColors.end(); ++it )
3689 mimeColors << qMakePair( *it, QString() );
3693 if ( mimeColors.length() == 0 && data->hasColor() )
3696 const QColor mimeColor = data->colorData().value<QColor>();
3697 if ( mimeColor.isValid() )
3699 mimeColors << qMakePair( mimeColor, QString() );
3709 QMimeData *mimeData =
new QMimeData();
3710 QDomDocument xmlDoc;
3711 QDomElement xmlRootElement = xmlDoc.createElement( QStringLiteral(
"ColorSchemeModelDragData" ) );
3712 xmlDoc.appendChild( xmlRootElement );
3714 QgsNamedColorList::const_iterator colorIt = colorList.constBegin();
3715 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3717 QDomElement namedColor = xmlDoc.createElement( QStringLiteral(
"NamedColor" ) );
3719 namedColor.setAttribute( QStringLiteral(
"label" ), ( *colorIt ).second );
3720 xmlRootElement.appendChild( namedColor );
3722 mimeData->setData( QStringLiteral(
"text/xml" ), xmlDoc.toByteArray() );
3730 colorIt = colorList.constBegin();
3731 QStringList colorListString;
3732 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3734 colorListString << ( *colorIt ).first.name();
3736 mimeData->setText( colorListString.join( QLatin1Char(
'\n' ) ) );
3739 if ( colorList.length() > 0 )
3741 mimeData->setColorData( QVariant( colorList.at( 0 ).first ) );
3749 if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3754 QTextStream stream( &file );
3755 stream <<
"GIMP Palette" << Qt::endl;
3756 if ( paletteName.isEmpty() )
3758 stream <<
"Name: QGIS Palette" << Qt::endl;
3762 stream <<
"Name: " << paletteName << Qt::endl;
3764 stream <<
"Columns: 4" << Qt::endl;
3765 stream <<
'#' << Qt::endl;
3767 for ( QgsNamedColorList::ConstIterator colorIt = colors.constBegin(); colorIt != colors.constEnd(); ++colorIt )
3769 const QColor color = ( *colorIt ).first;
3770 if ( !color.isValid() )
3774 stream << QStringLiteral(
"%1 %2 %3" ).arg( color.red(), 3 ).arg( color.green(), 3 ).arg( color.blue(), 3 );
3775 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << Qt::endl;
3786 if ( !file.open( QIODevice::ReadOnly ) )
3789 return importedColors;
3792 QTextStream in( &file );
3794 QString line = in.readLine();
3795 if ( !line.startsWith( QLatin1String(
"GIMP Palette" ) ) )
3798 return importedColors;
3802 while ( !in.atEnd() && !line.startsWith( QLatin1String(
"Name:" ) ) && !line.startsWith(
'#' ) )
3804 line = in.readLine();
3806 if ( line.startsWith( QLatin1String(
"Name:" ) ) )
3808 const thread_local QRegularExpression nameRx(
"Name:\\s*(\\S.*)$" );
3809 const QRegularExpressionMatch match = nameRx.match( line );
3810 if ( match.hasMatch() )
3812 name = match.captured( 1 );
3817 while ( !in.atEnd() && !line.startsWith(
'#' ) )
3819 line = in.readLine();
3824 return importedColors;
3828 const thread_local QRegularExpression rx(
"^\\s*(\\d+)\\s+(\\d+)\\s+(\\d+)(\\s.*)?$" );
3829 while ( !in.atEnd() )
3831 line = in.readLine();
3832 const QRegularExpressionMatch match = rx.match( line );
3833 if ( !match.hasMatch() )
3837 const int red = match.captured( 1 ).toInt();
3838 const int green = match.captured( 2 ).toInt();
3839 const int blue = match.captured( 3 ).toInt();
3840 const QColor color = QColor( red, green, blue );
3841 if ( !color.isValid() )
3848 if ( rx.captureCount() > 3 )
3850 label = match.captured( 4 ).simplified();
3857 importedColors << qMakePair( color, label );
3862 return importedColors;
3875 const thread_local QRegularExpression hexColorAlphaRx(
"^\\s*#?([0-9a-fA-F]{6})([0-9a-fA-F]{2})\\s*$" );
3876 QRegularExpressionMatch match = hexColorAlphaRx.match( colorStr );
3879 if ( !match.hasMatch() && QColor::isValidColor( colorStr ) )
3882 parsedColor.setNamedColor( colorStr );
3883 if ( parsedColor.isValid() )
3885 containsAlpha =
false;
3891 if ( match.hasMatch() )
3893 const QString hexColor = match.captured( 1 );
3894 parsedColor.setNamedColor( QStringLiteral(
"#" ) + hexColor );
3896 const int alphaHex = match.captured( 2 ).toInt( &alphaOk, 16 );
3898 if ( parsedColor.isValid() && alphaOk )
3900 parsedColor.setAlpha( alphaHex );
3901 containsAlpha =
true;
3909 const thread_local QRegularExpression hexColorRx2(
"^\\s*(?:[0-9a-fA-F]{3}){1,2}\\s*$" );
3910 if ( colorStr.indexOf( hexColorRx2 ) != -1 )
3913 parsedColor.setNamedColor( QStringLiteral(
"#" ) + colorStr );
3914 if ( parsedColor.isValid() )
3916 containsAlpha =
false;
3923 const thread_local QRegularExpression rgbFormatRx(
"^\\s*(?:rgb)?\\(?\\s*([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\s*,\\s*([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\s*,\\s*([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\s*\\)?\\s*;?\\s*$" );
3924 match = rgbFormatRx.match( colorStr );
3925 if ( match.hasMatch() )
3927 const int r = match.captured( 1 ).toInt();
3928 const int g = match.captured( 2 ).toInt();
3929 const int b = match.captured( 3 ).toInt();
3930 parsedColor.setRgb( r, g, b );
3931 if ( parsedColor.isValid() )
3933 containsAlpha =
false;
3939 const thread_local QRegularExpression hslFormatRx(
"^\\s*hsl\\(?\\s*(\\d+)\\s*,\\s*(\\d+)\\s*%\\s*,\\s*(\\d+)\\s*%\\s*\\)?\\s*;?\\s*$" );
3940 match = hslFormatRx.match( colorStr );
3941 if ( match.hasMatch() )
3943 const int h = match.captured( 1 ).toInt();
3944 const int s = match.captured( 2 ).toInt();
3945 const int l = match.captured( 3 ).toInt();
3946 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0 );
3947 if ( parsedColor.isValid() )
3949 containsAlpha =
false;
3955 const thread_local QRegularExpression rgbPercentFormatRx(
"^\\s*(?:rgb)?\\(?\\s*(100|0*\\d{1,2})\\s*%\\s*,\\s*(100|0*\\d{1,2})\\s*%\\s*,\\s*(100|0*\\d{1,2})\\s*%\\s*\\)?\\s*;?\\s*$" );
3956 match = rgbPercentFormatRx.match( colorStr );
3957 if ( match.hasMatch() )
3959 const int r = std::round( match.captured( 1 ).toDouble() * 2.55 );
3960 const int g = std::round( match.captured( 2 ).toDouble() * 2.55 );
3961 const int b = std::round( match.captured( 3 ).toDouble() * 2.55 );
3962 parsedColor.setRgb( r, g, b );
3963 if ( parsedColor.isValid() )
3965 containsAlpha =
false;
3971 const thread_local QRegularExpression rgbaFormatRx(
"^\\s*(?:rgba)?\\(?\\s*([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\s*,\\s*([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\s*,\\s*([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\s*,\\s*(0|0?\\.\\d*|1(?:\\.0*)?)\\s*\\)?\\s*;?\\s*$" );
3972 match = rgbaFormatRx.match( colorStr );
3973 if ( match.hasMatch() )
3975 const int r = match.captured( 1 ).toInt();
3976 const int g = match.captured( 2 ).toInt();
3977 const int b = match.captured( 3 ).toInt();
3978 const int a = std::round( match.captured( 4 ).toDouble() * 255.0 );
3979 parsedColor.setRgb( r, g, b, a );
3980 if ( parsedColor.isValid() )
3982 containsAlpha =
true;
3988 const thread_local QRegularExpression rgbaPercentFormatRx(
"^\\s*(?:rgba)?\\(?\\s*(100|0*\\d{1,2})\\s*%\\s*,\\s*(100|0*\\d{1,2})\\s*%\\s*,\\s*(100|0*\\d{1,2})\\s*%\\s*,\\s*(0|0?\\.\\d*|1(?:\\.0*)?)\\s*\\)?\\s*;?\\s*$" );
3989 match = rgbaPercentFormatRx.match( colorStr );
3990 if ( match.hasMatch() )
3992 const int r = std::round( match.captured( 1 ).toDouble() * 2.55 );
3993 const int g = std::round( match.captured( 2 ).toDouble() * 2.55 );
3994 const int b = std::round( match.captured( 3 ).toDouble() * 2.55 );
3995 const int a = std::round( match.captured( 4 ).toDouble() * 255.0 );
3996 parsedColor.setRgb( r, g, b, a );
3997 if ( parsedColor.isValid() )
3999 containsAlpha =
true;
4005 const thread_local QRegularExpression hslaPercentFormatRx(
"^\\s*hsla\\(?\\s*(\\d+)\\s*,\\s*(\\d+)\\s*%\\s*,\\s*(\\d+)\\s*%\\s*,\\s*([\\d\\.]+)\\s*\\)?\\s*;?\\s*$" );
4006 match = hslaPercentFormatRx.match( colorStr );
4007 if ( match.hasMatch() )
4009 const int h = match.captured( 1 ).toInt();
4010 const int s = match.captured( 2 ).toInt();
4011 const int l = match.captured( 3 ).toInt();
4012 const int a = std::round( match.captured( 4 ).toDouble() * 255.0 );
4013 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0, a );
4014 if ( parsedColor.isValid() )
4016 containsAlpha =
true;
4033 const QImage::Format format = image->format();
4034 if ( format != QImage::Format_ARGB32_Premultiplied && format != QImage::Format_ARGB32 )
4041 for (
int heightIndex = 0; heightIndex < image->height(); ++heightIndex )
4043 QRgb *scanLine =
reinterpret_cast< QRgb *
>( image->scanLine( heightIndex ) );
4044 for (
int widthIndex = 0; widthIndex < image->width(); ++widthIndex )
4046 myRgb = scanLine[widthIndex];
4047 if ( format == QImage::Format_ARGB32_Premultiplied )
4048 scanLine[widthIndex] = qRgba( opacity * qRed( myRgb ), opacity * qGreen( myRgb ), opacity * qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4050 scanLine[widthIndex] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4058 const int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
4059 const int alpha = ( radius < 1 ) ? 16 : ( radius > 17 ) ? 1 : tab[radius - 1];
4061 if ( image.format() != QImage::Format_ARGB32_Premultiplied
4062 && image.format() != QImage::Format_RGB32 )
4064 image = image.convertToFormat( QImage::Format_ARGB32_Premultiplied );
4067 const int r1 = rect.top();
4068 const int r2 = rect.bottom();
4069 const int c1 = rect.left();
4070 const int c2 = rect.right();
4072 const int bpl = image.bytesPerLine();
4080 i1 = i2 = ( QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3 );
4082 for (
int col = c1; col <= c2; col++ )
4084 p = image.scanLine( r1 ) + col * 4;
4085 for (
int i = i1; i <= i2; i++ )
4086 rgba[i] = p[i] << 4;
4089 for (
int j = r1; j < r2; j++, p += bpl )
4090 for (
int i = i1; i <= i2; i++ )
4091 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4094 for (
int row = r1; row <= r2; row++ )
4096 p = image.scanLine( row ) + c1 * 4;
4097 for (
int i = i1; i <= i2; i++ )
4098 rgba[i] = p[i] << 4;
4101 for (
int j = c1; j < c2; j++, p += 4 )
4102 for (
int i = i1; i <= i2; i++ )
4103 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4106 for (
int col = c1; col <= c2; col++ )
4108 p = image.scanLine( r2 ) + col * 4;
4109 for (
int i = i1; i <= i2; i++ )
4110 rgba[i] = p[i] << 4;
4113 for (
int j = r1; j < r2; j++, p -= bpl )
4114 for (
int i = i1; i <= i2; i++ )
4115 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4118 for (
int row = r1; row <= r2; row++ )
4120 p = image.scanLine( row ) + c2 * 4;
4121 for (
int i = i1; i <= i2; i++ )
4122 rgba[i] = p[i] << 4;
4125 for (
int j = c1; j < c2; j++, p -= 4 )
4126 for (
int i = i1; i <= i2; i++ )
4127 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4133 if ( alpha != 255 && alpha > 0 )
4137 const double alphaFactor = alpha / 255.;
4138 int r = 0, g = 0, b = 0;
4139 rgb.getRgb( &r, &g, &b );
4144 rgb.setRgb( r, g, b, alpha );
4146 else if ( alpha == 0 )
4148 rgb.setRgb( 0, 0, 0, 0 );
4157 if ( !simpleFill || !simpleLine )
4181 if ( simpleLine->
offset() )
4199 if ( order == Qt::AscendingOrder )
4213 const double dx = directionPoint.x() - startPoint.x();
4214 const double dy = directionPoint.y() - startPoint.y();
4215 const double length = std::sqrt( dx * dx + dy * dy );
4216 const double scaleFactor = distance / length;
4217 return QPointF( startPoint.x() + dx * scaleFactor, startPoint.y() + dy * scaleFactor );
4227 for (
int i = 0; i < svgPaths.size(); i++ )
4229 const QDir dir( svgPaths[i] );
4230 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4231 for (
const QString &item : svgSubPaths )
4233 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4236 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4237 for (
const QString &item : svgFiles )
4240 list.append( dir.path() +
'/' + item );
4252 QStringList svgPaths;
4253 svgPaths.append( directory );
4255 for (
int i = 0; i < svgPaths.size(); i++ )
4257 const QDir dir( svgPaths[i] );
4258 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4259 for (
const QString &item : svgSubPaths )
4261 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4264 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4265 for (
const QString &item : svgFiles )
4267 list.append( dir.path() +
'/' + item );
4279 if ( n.startsWith( QLatin1String(
"base64:" ) ) )
4283 if ( QFileInfo::exists( n ) )
4284 return QFileInfo( n ).canonicalFilePath();
4288 if ( name.contains( QLatin1String(
"://" ) ) )
4290 const QUrl url( name );
4291 if ( url.isValid() && !url.scheme().isEmpty() )
4293 if ( url.scheme().compare( QLatin1String(
"file" ), Qt::CaseInsensitive ) == 0 )
4296 name = url.toLocalFile();
4297 if ( QFile( name ).exists() )
4299 return QFileInfo( name ).canonicalFilePath();
4313 for (
int i = 0; i < svgPaths.size(); i++ )
4315 QString svgPath = svgPaths[i];
4316 if ( svgPath.endsWith( QChar(
'/' ) ) )
4327 const QString myLocalPath = svgPath + QDir::separator() + name;
4330 if ( QFile( myLocalPath ).exists() )
4333 return QFileInfo( myLocalPath ).canonicalFilePath();
4337 return pathResolver.
readPath( name );
4345 if ( p.startsWith( QLatin1String(
"base64:" ) ) )
4348 if ( !QFileInfo::exists( p ) )
4351 QString path = QFileInfo( p ).canonicalFilePath();
4355 bool isInSvgPaths =
false;
4356 for (
int i = 0; i < svgPaths.size(); i++ )
4358 const QString dir = QFileInfo( svgPaths[i] ).canonicalFilePath();
4360 if ( !dir.isEmpty() && path.startsWith( dir ) )
4362 path = path.mid( dir.size() + 1 );
4363 isInSvgPaths =
true;
4378 double cx = 0, cy = 0;
4379 double area, sum = 0;
4380 for (
int i = points.count() - 1, j = 0; j < points.count(); i = j++ )
4382 const QPointF &p1 = points[i];
4383 const QPointF &p2 = points[j];
4384 area = p1.x() * p2.y() - p1.y() * p2.x();
4386 cx += ( p1.x() + p2.x() ) * area;
4387 cy += ( p1.y() + p2.y() ) * area;
4394 if ( points.count() >= 2 )
4395 return QPointF( ( points[0].x() + points[1].x() ) / 2, ( points[0].y() + points[1].y() ) / 2 );
4396 else if ( points.count() == 1 )
4404 return QPointF( cx, cy );
4411 if ( ( rings && rings->count() > 0 ) || !
pointInPolygon( points, centroid ) )
4413 unsigned int i, pointCount = points.count();
4415 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( points[i].x(), points[i].y() );
4421 for (
auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
4423 pointCount = ( *ringIt ).count();
4425 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( ( *ringIt )[i].x(), ( *ringIt )[i].y() );
4431 if ( !pointOnSurfaceGeom.
isNull() )
4434 centroid.
setX( point.
x() );
4435 centroid.
setY( point.
y() );
4440 return QPointF( centroid.
x(), centroid.
y() );
4445 bool inside =
false;
4447 const double x = point.x();
4448 const double y = point.y();
4450 for (
int i = 0, j = points.count() - 1; i < points.count(); i++ )
4452 const QPointF &p1 = points[i];
4453 const QPointF &p2 = points[j];
4458 if ( ( p1.y() < y && p2.y() >= y ) || ( p2.y() < y && p1.y() >= y ) )
4460 if ( p1.x() + ( y - p1.y() ) / ( p2.y() - p1.y() ) * ( p2.x() - p1.x() ) <= x )
4471 if ( polyline.size() < 2 )
4474 double totalLength = 0;
4475 auto it = polyline.begin();
4477 for ( ; it != polyline.end(); ++it )
4479 const QPointF p2 = *it;
4480 const double segmentLength = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4481 totalLength += segmentLength;
4489 if ( polyline.size() < 2 )
4492 double totalLength = 0;
4493 auto it = polyline.begin();
4495 std::vector< double > segmentLengths( polyline.size() - 1 );
4496 auto segmentLengthIt = segmentLengths.begin();
4497 for ( ; it != polyline.end(); ++it )
4499 const QPointF p2 = *it;
4500 *segmentLengthIt = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4501 totalLength += *segmentLengthIt;
4507 if ( startOffset >= 0 && totalLength <= startOffset )
4509 if ( endOffset < 0 && totalLength <= -endOffset )
4512 const double startDistance = startOffset < 0 ? totalLength + startOffset : startOffset;
4513 const double endDistance = endOffset <= 0 ? totalLength + endOffset : endOffset;
4514 QPolygonF substringPoints;
4515 substringPoints.reserve( polyline.size() );
4517 it = polyline.begin();
4518 segmentLengthIt = segmentLengths.begin();
4521 bool foundStart =
false;
4522 if (
qgsDoubleNear( startDistance, 0.0 ) || startDistance < 0 )
4524 substringPoints << p1;
4528 double distanceTraversed = 0;
4529 for ( ; it != polyline.end(); ++it )
4531 const QPointF p2 = *it;
4532 if ( distanceTraversed < startDistance && distanceTraversed + *segmentLengthIt > startDistance )
4535 const double distanceToStart = startDistance - distanceTraversed;
4536 double startX, startY;
4538 substringPoints << QPointF( startX, startY );
4541 if ( foundStart && ( distanceTraversed + *segmentLengthIt > endDistance ) )
4544 const double distanceToEnd = endDistance - distanceTraversed;
4547 if ( substringPoints.last() != QPointF( endX, endY ) )
4548 substringPoints << QPointF( endX, endY );
4550 else if ( foundStart )
4552 if ( substringPoints.last() != QPointF( p2.x(), p2.y() ) )
4553 substringPoints << QPointF( p2.x(), p2.y() );
4556 distanceTraversed += *segmentLengthIt;
4557 if ( distanceTraversed > endDistance )
4564 if ( ( substringPoints.size() < 2 ) || ( substringPoints.size() == 2 && substringPoints.at( 0 ) == substringPoints.at( 1 ) ) )
4567 return substringPoints;
4572 double vertexAngle = M_PI - ( std::atan2( p3.y() - p2.y(), p3.x() - p2.x() ) - std::atan2( p2.y() - p1.y(), p2.x() - p1.x() ) );
4576 return vertexAngle < M_PI * 135.0 / 180.0 || vertexAngle > M_PI * 225.0 / 180.0;
4581 target.reserve( target.size() + line.size() );
4582 for (
const QPointF &pt : line )
4584 if ( !target.empty() && target.last() == pt )
4593 if ( fieldOrExpression.isEmpty() )
4628 QList<double> breaks;
4631 breaks.append( maximum );
4635 const int minimumCount =
static_cast< int >( classes ) / 3;
4636 const double shrink = 0.75;
4637 const double highBias = 1.5;
4638 const double adjustBias = 0.5 + 1.5 * highBias;
4639 const int divisions = classes;
4640 const double h = highBias;
4643 const double dx = maximum - minimum;
4653 cell = std::max( std::fabs( minimum ), std::fabs( maximum ) );
4654 if ( adjustBias >= 1.5 * h + 0.5 )
4656 U = 1 + ( 1.0 / ( 1 + h ) );
4660 U = 1 + ( 1.5 / ( 1 + adjustBias ) );
4662 small = dx < ( cell * U * std::max( 1, divisions ) * 1e-07 * 3.0 );
4669 cell = 9 + cell / 10;
4670 cell = cell * shrink;
4672 if ( minimumCount > 1 )
4674 cell = cell / minimumCount;
4680 if ( divisions > 1 )
4682 cell = cell / divisions;
4685 if ( cell < 20 * 1e-07 )
4690 const double base = std::pow( 10.0, std::floor( std::log10( cell ) ) );
4692 if ( ( 2 * base ) - cell < h * ( cell - unit ) )
4695 if ( ( 5 * base ) - cell < adjustBias * ( cell - unit ) )
4698 if ( ( 10.0 * base ) - cell < h * ( cell - unit ) )
4705 int start = std::floor( minimum / unit + 1e-07 );
4706 int end = std::ceil( maximum / unit - 1e-07 );
4709 while ( start * unit > minimum + ( 1e-07 * unit ) )
4713 while ( end * unit < maximum - ( 1e-07 * unit ) )
4721 int k = std::floor( 0.5 + end - start );
4722 if ( k < minimumCount )
4724 k = minimumCount - k;
4728 start = start - k / 2 + k % 2;
4732 start = start - k / 2;
4733 end = end + k / 2 + k % 2;
4736 const double minimumBreak = start * unit;
4738 const int count = end - start;
4740 breaks.reserve( count );
4741 for (
int i = 1; i < count + 1; i++ )
4743 breaks.append( minimumBreak + i * unit );
4746 if ( breaks.isEmpty() )
4749 if ( breaks.first() < minimum )
4751 breaks[0] = minimum;
4753 if ( breaks.last() > maximum )
4755 breaks[breaks.count() - 1] = maximum;
4760 if ( minimum < 0.0 && maximum > 0.0 )
4762 QList<double> breaksMinusZero;
4763 for (
int i = 0; i < breaks.count(); i++ )
4765 breaksMinusZero.append( breaks[i] - 0.0 );
4768 for (
int i = 1; i < breaks.count(); i++ )
4770 if ( std::abs( breaksMinusZero[i] ) < std::abs( breaksMinusZero[i - 1] ) )
4773 breaks[posOfMin] = 0.0;
4782 bool roundToUnit =
false;
4785 if ( props.contains( QStringLiteral(
"uomScale" ) ) )
4788 scale = props.value( QStringLiteral(
"uomScale" ) ).toDouble( &ok );
4797 if ( props.value( QStringLiteral(
"uom" ) ) == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
4822 scale = 1 / 0.28 * 25.4;
4846 double rescaled = size * scale;
4851 rescaled = std::round( rescaled );
4858 const double x =
rescaleUom( point.x(), unit, props );
4859 const double y =
rescaleUom( point.y(), unit, props );
4860 return QPointF( x, y );
4865 QVector<qreal> result;
4866 QVector<qreal>::const_iterator it = array.constBegin();
4867 for ( ; it != array.constEnd(); ++it )
4869 result.append(
rescaleUom( *it, unit, props ) );
4876 if ( !props.value( QStringLiteral(
"scaleMinDenom" ), QString() ).toString().isEmpty() )
4878 QDomElement scaleMinDenomElem = doc.createElement( QStringLiteral(
"se:MinScaleDenominator" ) );
4879 scaleMinDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMinDenom" ) ).toString().toDouble() ) ) );
4880 ruleElem.appendChild( scaleMinDenomElem );
4883 if ( !props.value( QStringLiteral(
"scaleMaxDenom" ), QString() ).toString().isEmpty() )
4885 QDomElement scaleMaxDenomElem = doc.createElement( QStringLiteral(
"se:MaxScaleDenominator" ) );
4886 scaleMaxDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMaxDenom" ) ).toString().toDouble() ) ) );
4887 ruleElem.appendChild( scaleMaxDenomElem );
4896 const double parentScaleMinDenom = props.value( QStringLiteral(
"scaleMinDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
4897 if ( !ok || parentScaleMinDenom <= 0 )
4898 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( mScaleMinDenom );
4900 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( std::max( parentScaleMinDenom, mScaleMinDenom ) );
4906 const double parentScaleMaxDenom = props.value( QStringLiteral(
"scaleMaxDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
4907 if ( !ok || parentScaleMaxDenom <= 0 )
4908 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( mScaleMaxDenom );
4910 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( std::min( parentScaleMaxDenom, mScaleMaxDenom ) );
4918 if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
4920 scale = 1.0 / 0.00028;
4922 else if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
4924 scale = 304.8 / 0.28;
4931 return size * scale;
4939 SymbolLayerVisitor(
const QSet<QgsSymbolLayerId> &layerIds )
4940 : mSymbolLayerIds( layerIds )
4953 void visitSymbol(
const QgsSymbol *symbol,
const QString &identifier, QVector<int> rootPath )
4957 QVector<int> indexPath = rootPath;
4958 indexPath.append( idx );
4960 if ( mSymbolLayerIds.contains(
QgsSymbolLayerId( mCurrentRuleKey + identifier, indexPath ) ) )
4962 mSymbolLayers.insert( sl );
4967 visitSymbol( subSymbol, identifier, indexPath );
4976 if ( symbolEntity->symbol() )
4978 visitSymbol( symbolEntity->symbol(), leaf.
identifier, {} );
4984 QString mCurrentRuleKey;
4985 const QSet<QgsSymbolLayerId> &mSymbolLayerIds;
4986 QSet<const QgsSymbolLayer *> mSymbolLayers;
4989 SymbolLayerVisitor visitor( symbolLayerIds );
4990 renderer->
accept( &visitor );
4991 return visitor.mSymbolLayers;
4999 SymbolRefreshRateVisitor()
5011 void visitSymbol(
const QgsSymbol *symbol )
5028 if ( refreshRate == -1 || ( animatedMarker->frameRate() > refreshRate ) )
5029 refreshRate = animatedMarker->frameRate();
5033 visitSymbol( subSymbol );
5041 if (
QgsSymbol *symbol = qgis::down_cast<const QgsStyleSymbolEntity *>( leaf.
entity )->symbol() )
5043 visitSymbol( symbol );
5049 double refreshRate = -1;
5052 SymbolRefreshRateVisitor visitor;
5053 renderer->
accept( &visitor );
5054 return visitor.refreshRate;
5059 if ( !s || !context )
5085 size = markerSymbol->
size( *context );
5087 else if ( lineSymbol )
5089 size = lineSymbol->
width( *context );
5101 if ( minSize > 0 && size < minSize )
5105 else if ( maxSize > 0 && size > maxSize )
5124 else if ( lineSymbol )
5139 QMap<QString, QgsProperty>::const_iterator paramIt = propertiesMap.constBegin();
5140 for ( ; paramIt != propertiesMap.constEnd(); ++paramIt )
5142 properties.insert( paramIt.key(), paramIt.value().valueAsString( context ) );
5150 angleRad = std::fmod( angleRad, M_PI * 2 );
5154 angleRad += M_PI * 2;
5158 struct rationalTangent
5170 static const QList<rationalTangent> __rationalTangents
5172 { 1, 57, 0.01754206006 },
5173 { 3, 86, 0.03486958155 },
5174 { 1, 19, 0.05258306161 },
5175 { 3, 43, 0.06965457373 },
5176 { 7, 80, 0.08727771295 },
5177 { 2, 19, 0.1048769387 },
5178 { 7, 57, 0.1221951707 },
5179 { 9, 64, 0.1397088743 },
5180 { 13, 82, 0.157228051 },
5181 { 3, 17, 0.174672199 },
5182 { 7, 36, 0.1920480172 },
5183 { 17, 80, 0.209385393 },
5184 { 3, 13, 0.2267988481 },
5185 { 1, 4, 0.2449786631 },
5186 { 26, 97, 0.2618852647 },
5187 { 27, 94, 0.2797041525 },
5188 { 26, 85, 0.2968446734 },
5189 { 13, 40, 0.3142318991 },
5190 { 21, 61, 0.3315541619 },
5191 { 4, 11, 0.3487710036 },
5192 { 38, 99, 0.3664967859 },
5193 { 40, 99, 0.383984624 },
5194 { 31, 73, 0.4015805401 },
5195 { 41, 92, 0.4192323938 },
5196 { 7, 15, 0.4366271598 },
5197 { 20, 41, 0.4538440015 },
5198 { 27, 53, 0.4711662643 },
5199 { 42, 79, 0.4886424026 },
5200 { 51, 92, 0.5061751436 },
5201 { 56, 97, 0.5235757641 },
5202 { 3, 5, 0.5404195003 },
5203 { 5, 8, 0.5585993153 },
5204 { 50, 77, 0.5759185996 },
5205 { 29, 43, 0.5933501462 },
5206 { 7, 10, 0.6107259644 },
5207 { 69, 95, 0.6281701124 },
5208 { 52, 69, 0.6458159195 },
5209 { 25, 32, 0.6632029927 },
5210 { 17, 21, 0.6805212247 },
5211 { 73, 87, 0.6981204504 },
5212 { 73, 84, 0.7154487784 },
5213 { 9, 10, 0.7328151018 },
5214 { 83, 89, 0.7505285818 },
5215 { 28, 29, 0.7678561033 },
5216 { 1, 1, 0.7853981634 },
5217 { 29, 28, 0.8029402235 },
5218 { 89, 83, 0.820267745 },
5219 { 10, 9, 0.837981225 },
5220 { 107, 93, 0.855284165 },
5221 { 87, 73, 0.8726758763 },
5222 { 121, 98, 0.8900374031 },
5223 { 32, 25, 0.9075933341 },
5224 { 69, 52, 0.9249804073 },
5225 { 128, 93, 0.9424647244 },
5226 { 10, 7, 0.9600703624 },
5227 { 43, 29, 0.9774461806 },
5228 { 77, 50, 0.9948777272 },
5229 { 8, 5, 1.012197011 },
5230 { 163, 98, 1.029475114 },
5231 { 168, 97, 1.047174539 },
5232 { 175, 97, 1.064668696 },
5233 { 126, 67, 1.082075603 },
5234 { 157, 80, 1.099534652 },
5235 { 203, 99, 1.117049384 },
5236 { 193, 90, 1.134452855 },
5237 { 146, 65, 1.151936673 },
5238 { 139, 59, 1.169382787 },
5239 { 99, 40, 1.186811703 },
5240 { 211, 81, 1.204257817 },
5241 { 272, 99, 1.221730164 },
5242 { 273, 94, 1.239188479 },
5243 { 277, 90, 1.25664606 },
5244 { 157, 48, 1.274088705 },
5245 { 279, 80, 1.291550147 },
5246 { 362, 97, 1.308990773 },
5247 { 373, 93, 1.326448578 },
5248 { 420, 97, 1.343823596 },
5249 { 207, 44, 1.361353157 },
5250 { 427, 83, 1.378810994 },
5251 { 414, 73, 1.396261926 },
5252 { 322, 51, 1.413716057 },
5253 { 185, 26, 1.431170275 },
5254 { 790, 97, 1.448623034 },
5255 { 333, 35, 1.466075711 },
5256 { 1063, 93, 1.483530284 },
5257 { 1330, 93, 1.500985147 },
5258 { 706, 37, 1.518436297 },
5259 { 315, 11, 1.535889876 },
5260 { 3953, 69, 1.553343002 },
5266 static const QList<rationalTangent> rationalTangents
5268 { 1, 10, qDegreesToRadians( 5.71059 ) },
5269 { 1, 5, qDegreesToRadians( 11.3099 ) },
5270 { 1, 4, qDegreesToRadians( 14.0362 ) },
5271 { 1, 4, qDegreesToRadians( 18.4349 ) },
5272 { 1, 2, qDegreesToRadians( 26.5651 ) },
5273 { 2, 3, qDegreesToRadians( 33.6901 ) },
5274 { 1, 1, qDegreesToRadians( 45.0 ) },
5275 { 3, 2, qDegreesToRadians( 56.3099 ) },
5276 { 2, 1, qDegreesToRadians( 63.4349 ) },
5277 { 3, 1, qDegreesToRadians( 71.5651 ) },
5278 { 4, 1, qDegreesToRadians( 75.9638 ) },
5279 { 10, 1, qDegreesToRadians( 84.2894 ) },
5282 const int quadrant {
static_cast<int>( angleRad / M_PI_2 ) };
5283 Q_ASSERT( quadrant >= 0 && quadrant <= 3 );
5295 angleRad -= M_PI / 2;
5305 angleRad -= M_PI + M_PI_2;
5327 for (
int idx = 0; idx < rationalTangents.count(); ++idx )
5329 const auto item = rationalTangents.at( idx );
5330 if (
qgsDoubleNear( item.angle, angleRad, 10E-3 ) || item.angle > angleRad )
5337 const rationalTangent bTan { rationalTangents.at( rTanIdx ) };
5338 angleRad = bTan.angle;
5339 const double k { bTan.q *height *width / std::cos( angleRad ) };
5340 const int hcfH { std::gcd( bTan.p * height, bTan.q * width ) };
5341 const int hcfW { std::gcd( bTan.q * height, bTan.p * width ) };
5342 const int W1 {
static_cast<int>( std::round( k / hcfW ) ) };
5343 const int H1 {
static_cast<int>( std::round( k / hcfH ) ) };
5356 angleRad += M_PI / 2;
5369 angleRad += M_PI + M_PI_2;
5380template <
typename Functor>
5383 sl->
setId( generateId() );
5391template <
typename Functor>
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.
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.
SymbolType
Attribute editing capabilities which may be supported by vector data providers.
@ 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 QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates the symbol layer.
static QString typeString()
Returns the string identifier for QgsCptCityColorRamp.
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.
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
static double normalizedAngle(double angle)
Ensures that an angle is in the range 0 <= angle < 2 pi.
static QgsPoint pointOnLineWithDistance(const QgsPoint &startPoint, const QgsPoint &directionPoint, double distance)
Returns a point a specified distance toward a second point.
A geometry is the spatial representation of a feature.
QgsMultiPolygonXY asMultiPolygon() const
Returns the contents of the geometry as a multi-polygon.
QgsGeometry offsetCurve(double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit) const
Returns an offset line at a given distance and side from an input line.
QgsGeometry pointOnSurface() const
Returns a point guaranteed to lie on the surface of a geometry.
static QgsGeometry fromPolylineXY(const QgsPolylineXY &polyline)
Creates a new LineString geometry from a list of QgsPointXY points.
QgsPolygonXY asPolygon() const
Returns the contents of the geometry as a polygon.
QgsPolylineXY asPolyline() const
Returns the contents of the geometry as a polyline.
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
Qgis::GeometryOperationResult addRing(const QVector< QgsPointXY > &ring)
Adds a new ring to this geometry.
QgsMultiPolylineXY asMultiPolyline() const
Returns the contents of the geometry as a multi-linestring.
static QgsGeometry fromPolygonXY(const QgsPolygonXY &polygon)
Creates a new geometry from a QgsPolygonXY.
QgsGeometry buffer(double distance, int segments) const
Returns a buffer region around this geometry having the given width and with a specified number of se...
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsColorRamp from a map of properties.
static QString typeString()
Returns the string identifier for QgsGradientColorRamp.
Represents a patch shape for use in map legends.
static QString typeString()
Returns the string identifier for QgsLimitedRandomColorRamp.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Returns a new QgsLimitedRandomColorRamp color ramp created using the properties encoded in a string m...
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.
QgsProperty property(int key) const override
Returns a matching property from the collection, if one exists.
QSet< int > propertyKeys() const override
Returns a list of property keys contained within the collection.
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.
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.
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.
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).
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 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 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)
Property
Data definable properties.
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...
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.
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.
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)
Returns true if the specified variant should be considered a NULL value.
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.
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.
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
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.