50#include <QDomDocument>
60#include <QRegularExpression>
63#define POINTS_TO_MM 2.83464567
67 return QStringLiteral(
"%1,%2,%3,%4" ).arg( color.red() ).arg( color.green() ).arg( color.blue() ).arg( color.alpha() );
72 const QStringList lst =
str.split(
',' );
73 if ( lst.count() < 3 )
77 int red, green, blue, alpha;
79 green = lst[1].toInt();
80 blue = lst[2].toInt();
82 if ( lst.count() > 3 )
84 alpha = lst[3].toInt();
86 return QColor( red, green, blue, alpha );
91 return QString::number( alpha / 255.0,
'g', 2 );
97 double alpha =
str.toDouble( &ok );
98 if ( !ok || alpha > 1 )
100 else if ( alpha < 0 )
109 case QFont::StyleNormal:
110 return QStringLiteral(
"normal" );
111 case QFont::StyleItalic:
112 return QStringLiteral(
"italic" );
113 case QFont::StyleOblique:
114 return QStringLiteral(
"oblique" );
122 if (
str == QLatin1String(
"normal" ) )
return QFont::StyleNormal;
123 if (
str == QLatin1String(
"italic" ) )
return QFont::StyleItalic;
124 if (
str == QLatin1String(
"oblique" ) )
return QFont::StyleOblique;
125 return QFont::StyleNormal;
130 if ( weight == 50 )
return QStringLiteral(
"normal" );
131 if ( weight == 75 )
return QStringLiteral(
"bold" );
135 if ( weight < 0 )
return QStringLiteral(
"100" );
136 if ( weight > 99 )
return QStringLiteral(
"900" );
137 return QString::number( weight * 800 / 99 + 100 );
143 const int weight =
str.toInt( &ok );
145 return static_cast< int >( QFont::Normal );
149 if ( weight > 900 )
return 99;
150 if ( weight < 100 )
return 0;
151 return ( weight - 100 ) * 99 / 800;
159 return QStringLiteral(
"no" );
161 return QStringLiteral(
"solid" );
163 return QStringLiteral(
"dash" );
165 return QStringLiteral(
"dot" );
166 case Qt::DashDotLine:
167 return QStringLiteral(
"dash dot" );
168 case Qt::DashDotDotLine:
169 return QStringLiteral(
"dash dot dot" );
171 return QStringLiteral(
"???" );
177 if (
str == QLatin1String(
"no" ) )
return Qt::NoPen;
178 if (
str == QLatin1String(
"solid" ) )
return Qt::SolidLine;
179 if (
str == QLatin1String(
"dash" ) )
return Qt::DashLine;
180 if (
str == QLatin1String(
"dot" ) )
return Qt::DotLine;
181 if (
str == QLatin1String(
"dash dot" ) )
return Qt::DashDotLine;
182 if (
str == QLatin1String(
"dash dot dot" ) )
return Qt::DashDotDotLine;
183 return Qt::SolidLine;
191 return QStringLiteral(
"bevel" );
193 return QStringLiteral(
"miter" );
195 return QStringLiteral(
"round" );
197 return QStringLiteral(
"???" );
203 const QString cleaned =
str.toLower().trimmed();
204 if ( cleaned == QLatin1String(
"bevel" ) )
205 return Qt::BevelJoin;
206 if ( cleaned == QLatin1String(
"miter" ) )
207 return Qt::MiterJoin;
208 if ( cleaned == QLatin1String(
"round" ) )
209 return Qt::RoundJoin;
210 return Qt::BevelJoin;
218 return QStringLiteral(
"bevel" );
220 return QStringLiteral(
"mitre" );
222 return QStringLiteral(
"round" );
230 if (
str == QLatin1String(
"bevel" ) )
return Qt::BevelJoin;
231 if (
str == QLatin1String(
"mitre" ) )
return Qt::MiterJoin;
232 if (
str == QLatin1String(
"round" ) )
return Qt::RoundJoin;
233 return Qt::BevelJoin;
241 return QStringLiteral(
"square" );
243 return QStringLiteral(
"flat" );
245 return QStringLiteral(
"round" );
247 return QStringLiteral(
"???" );
253 if (
str == QLatin1String(
"square" ) )
return Qt::SquareCap;
254 if (
str == QLatin1String(
"flat" ) )
return Qt::FlatCap;
255 if (
str == QLatin1String(
"round" ) )
return Qt::RoundCap;
256 return Qt::SquareCap;
264 return QStringLiteral(
"square" );
266 return QStringLiteral(
"butt" );
268 return QStringLiteral(
"round" );
276 if (
str == QLatin1String(
"square" ) )
return Qt::SquareCap;
277 if (
str == QLatin1String(
"butt" ) )
return Qt::FlatCap;
278 if (
str == QLatin1String(
"round" ) )
return Qt::RoundCap;
279 return Qt::SquareCap;
286 case Qt::SolidPattern :
287 return QStringLiteral(
"solid" );
288 case Qt::HorPattern :
289 return QStringLiteral(
"horizontal" );
290 case Qt::VerPattern :
291 return QStringLiteral(
"vertical" );
292 case Qt::CrossPattern :
293 return QStringLiteral(
"cross" );
294 case Qt::BDiagPattern :
295 return QStringLiteral(
"b_diagonal" );
296 case Qt::FDiagPattern :
297 return QStringLiteral(
"f_diagonal" );
298 case Qt::DiagCrossPattern :
299 return QStringLiteral(
"diagonal_x" );
300 case Qt::Dense1Pattern :
301 return QStringLiteral(
"dense1" );
302 case Qt::Dense2Pattern :
303 return QStringLiteral(
"dense2" );
304 case Qt::Dense3Pattern :
305 return QStringLiteral(
"dense3" );
306 case Qt::Dense4Pattern :
307 return QStringLiteral(
"dense4" );
308 case Qt::Dense5Pattern :
309 return QStringLiteral(
"dense5" );
310 case Qt::Dense6Pattern :
311 return QStringLiteral(
"dense6" );
312 case Qt::Dense7Pattern :
313 return QStringLiteral(
"dense7" );
315 return QStringLiteral(
"no" );
317 return QStringLiteral(
"???" );
323 if (
str == QLatin1String(
"solid" ) )
return Qt::SolidPattern;
324 if (
str == QLatin1String(
"horizontal" ) )
return Qt::HorPattern;
325 if (
str == QLatin1String(
"vertical" ) )
return Qt::VerPattern;
326 if (
str == QLatin1String(
"cross" ) )
return Qt::CrossPattern;
327 if (
str == QLatin1String(
"b_diagonal" ) )
return Qt::BDiagPattern;
328 if (
str == QLatin1String(
"f_diagonal" ) )
return Qt::FDiagPattern;
329 if (
str == QLatin1String(
"diagonal_x" ) )
return Qt::DiagCrossPattern;
330 if (
str == QLatin1String(
"dense1" ) )
return Qt::Dense1Pattern;
331 if (
str == QLatin1String(
"dense2" ) )
return Qt::Dense2Pattern;
332 if (
str == QLatin1String(
"dense3" ) )
return Qt::Dense3Pattern;
333 if (
str == QLatin1String(
"dense4" ) )
return Qt::Dense4Pattern;
334 if (
str == QLatin1String(
"dense5" ) )
return Qt::Dense5Pattern;
335 if (
str == QLatin1String(
"dense6" ) )
return Qt::Dense6Pattern;
336 if (
str == QLatin1String(
"dense7" ) )
return Qt::Dense7Pattern;
337 if (
str == QLatin1String(
"no" ) )
return Qt::NoBrush;
338 return Qt::SolidPattern;
345 case Qt::CrossPattern:
346 return QStringLiteral(
"cross" );
347 case Qt::DiagCrossPattern:
348 return QStringLiteral(
"x" );
355 return QStringLiteral(
"horline" );
357 return QStringLiteral(
"line" );
358 case Qt::BDiagPattern:
359 return QStringLiteral(
"slash" );
360 case Qt::FDiagPattern:
361 return QStringLiteral(
"backslash" );
364 case Qt::Dense1Pattern:
365 case Qt::Dense2Pattern:
366 case Qt::Dense3Pattern:
367 case Qt::Dense4Pattern:
368 case Qt::Dense5Pattern:
369 case Qt::Dense6Pattern:
370 case Qt::Dense7Pattern:
380 if (
str == QLatin1String(
"horline" ) )
return Qt::HorPattern;
381 if (
str == QLatin1String(
"line" ) )
return Qt::VerPattern;
382 if (
str == QLatin1String(
"cross" ) )
return Qt::CrossPattern;
383 if (
str == QLatin1String(
"slash" ) )
return Qt::BDiagPattern;
384 if (
str == QLatin1String(
"backshash" ) )
return Qt::FDiagPattern;
385 if (
str == QLatin1String(
"x" ) )
return Qt::DiagCrossPattern;
387 if (
str.startsWith( QLatin1String(
"brush://" ) ) )
395 const QString compareString =
string.trimmed();
399 if ( compareString.compare( QLatin1String(
"feature" ), Qt::CaseInsensitive ) == 0 )
401 else if ( compareString.compare( QLatin1String(
"viewport" ), Qt::CaseInsensitive ) == 0 )
411 switch ( coordinateReference )
414 return QStringLiteral(
"feature" );
416 return QStringLiteral(
"viewport" );
427 const QString s = value.toString().toLower().trimmed();
428 if ( s == QLatin1String(
"single" ) )
430 else if ( s == QLatin1String(
"reversed" ) )
432 else if ( s == QLatin1String(
"double" ) )
434 else if ( value.toInt() == 1 )
436 else if ( value.toInt() == 2 )
438 else if ( value.toInt( &intOk ) == 0 && intOk )
452 const QString s = value.toString().toLower().trimmed();
453 if ( s == QLatin1String(
"plain" ) )
455 else if ( s == QLatin1String(
"lefthalf" ) )
457 else if ( s == QLatin1String(
"righthalf" ) )
459 else if ( value.toInt() == 1 )
461 else if ( value.toInt() == 2 )
463 else if ( value.toInt( &intOk ) == 0 && intOk )
473 const QString compareString =
string.trimmed();
477 if ( compareString.compare( QLatin1String(
"no" ), Qt::CaseInsensitive ) == 0 )
479 else if ( compareString.compare( QLatin1String(
"shape" ), Qt::CaseInsensitive ) == 0 )
481 else if ( compareString.compare( QLatin1String(
"centroid_within" ), Qt::CaseInsensitive ) == 0 )
483 else if ( compareString.compare( QLatin1String(
"completely_within" ), Qt::CaseInsensitive ) == 0 )
496 return QStringLiteral(
"no" );
498 return QStringLiteral(
"shape" );
500 return QStringLiteral(
"centroid_within" );
502 return QStringLiteral(
"completely_within" );
509 const QString compareString =
string.trimmed();
513 if ( compareString.compare( QLatin1String(
"no" ), Qt::CaseInsensitive ) == 0 )
515 else if ( compareString.compare( QLatin1String(
"during_render" ), Qt::CaseInsensitive ) == 0 )
517 else if ( compareString.compare( QLatin1String(
"before_render" ), Qt::CaseInsensitive ) == 0 )
530 return QStringLiteral(
"no" );
532 return QStringLiteral(
"during_render" );
534 return QStringLiteral(
"before_render" );
546 QStringList lst =
str.split(
',' );
547 if ( lst.count() != 2 )
548 return QPointF( 0, 0 );
549 return QPointF( lst[0].toDouble(), lst[1].toDouble() );
560 if ( value.type() == QVariant::List )
562 const QVariantList list = value.toList();
563 if ( list.size() != 2 )
567 bool convertOk =
false;
568 const double x = list.at( 0 ).toDouble( &convertOk );
571 const double y = list.at( 1 ).toDouble( &convertOk );
576 return QPointF( x, y );
584 const QStringList list = value.toString().trimmed().split(
',' );
585 if ( list.count() != 2 )
587 bool convertOk =
false;
588 const double x = list.at( 0 ).toDouble( &convertOk );
591 const double y = list.at( 1 ).toDouble( &convertOk );
596 return QPointF( x, y );
610 QStringList lst =
string.split(
',' );
611 if ( lst.count() != 2 )
612 return QSizeF( 0, 0 );
613 return QSizeF( lst[0].toDouble(), lst[1].toDouble() );
624 if ( value.type() == QVariant::List )
626 const QVariantList list = value.toList();
627 if ( list.size() != 2 )
631 bool convertOk =
false;
632 const double x = list.at( 0 ).toDouble( &convertOk );
635 const double y = list.at( 1 ).toDouble( &convertOk );
640 return QSizeF( x, y );
648 const QStringList list = value.toString().trimmed().split(
',' );
649 if ( list.count() != 2 )
651 bool convertOk =
false;
652 const double x = list.at( 0 ).toDouble( &convertOk );
655 const double y = list.at( 1 ).toDouble( &convertOk );
660 return QSizeF( x, y );
681 if (
str.startsWith( QLatin1String(
"3x:" ) ) )
684 const QString chopped =
str.mid( 3 );
685 lst = chopped.split(
',' );
689 lst =
str.split(
',' );
691 if ( lst.count() < 2 )
694 double minScale = lst[0].toDouble();
696 minScale = minScale != 0 ? 1.0 / minScale : 0;
697 double maxScale = lst[1].toDouble();
699 maxScale = maxScale != 0 ? 1.0 / maxScale : 0;
701 if ( lst.count() < 6 )
721 *scaleFactor = 0.001;
722 return QStringLiteral(
"http://www.opengeospatial.org/se/units/metre" );
727 return QStringLiteral(
"http://www.opengeospatial.org/se/units/metre" );
734 *scaleFactor = 1 / 0.28;
743 if (
str == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
749 else if (
str == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
752 *scaleFactor = 0.3048;
767 QString vectorString;
768 QVector<qreal>::const_iterator it = v.constBegin();
769 for ( ; it != v.constEnd(); ++it )
771 if ( it != v.constBegin() )
773 vectorString.append(
';' );
775 vectorString.append( QString::number( *it ) );
782 QVector<qreal> resultVector;
784 const QStringList realList = s.split(
';' );
785 QStringList::const_iterator it = realList.constBegin();
786 for ( ; it != realList.constEnd(); ++it )
788 resultVector.append( it->toDouble() );
796 QString vectorString;
797 QVector<qreal>::const_iterator it = v.constBegin();
798 for ( ; it != v.constEnd(); ++it )
800 if ( it != v.constBegin() )
802 vectorString.append(
' ' );
804 vectorString.append( QString::number( *it ) );
811 QVector<qreal> resultVector;
813 const QStringList realList = s.split(
' ' );
814 QStringList::const_iterator it = realList.constBegin();
815 for ( ; it != realList.constEnd(); ++it )
817 resultVector.append( it->toDouble() );
825 QString encodedValue;
827 switch ( scaleMethod )
830 encodedValue = QStringLiteral(
"diameter" );
833 encodedValue = QStringLiteral(
"area" );
843 if (
str == QLatin1String(
"diameter" ) )
857 if ( s.compare( QLatin1String(
"Lighten" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Lighten;
858 if ( s.compare( QLatin1String(
"Screen" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Screen;
859 if ( s.compare( QLatin1String(
"Dodge" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorDodge;
860 if ( s.compare( QLatin1String(
"Addition" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Plus;
861 if ( s.compare( QLatin1String(
"Darken" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Darken;
862 if ( s.compare( QLatin1String(
"Multiply" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Multiply;
863 if ( s.compare( QLatin1String(
"Burn" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorBurn;
864 if ( s.compare( QLatin1String(
"Overlay" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Overlay;
865 if ( s.compare( QLatin1String(
"SoftLight" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_SoftLight;
866 if ( s.compare( QLatin1String(
"HardLight" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_HardLight;
867 if ( s.compare( QLatin1String(
"Difference" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Difference;
868 if ( s.compare( QLatin1String(
"Subtract" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Exclusion;
869 return QPainter::CompositionMode_SourceOver;
874 return QIcon(
symbolPreviewPixmap( symbol, size, padding,
nullptr,
false,
nullptr, shape, screen ) );
882 QPixmap pixmap( size * devicePixelRatio );
883 pixmap.setDevicePixelRatio( devicePixelRatio );
885 pixmap.fill( Qt::transparent );
887 painter.begin( &pixmap );
892 painter.setRenderHint( QPainter::Antialiasing );
893 painter.setRenderHint( QPainter::SmoothPixmapTransform );
903 size.setWidth( size.rwidth() - ( padding * 2 ) );
904 size.setHeight( size.rheight() - ( padding * 2 ) );
905 painter.translate( padding, padding );
915 std::unique_ptr<QgsSymbol> symbol_noDD( symbol->
clone( ) );
917 for (
const auto &layer : layers )
919 for (
int i = 0; i < layer->dataDefinedProperties().count(); ++i )
921 QgsProperty &prop = layer->dataDefinedProperties().property( i );
927 symbol_noDD->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape, screen );
931 std::unique_ptr<QgsSymbol> symbolClone( symbol->
clone( ) );
932 symbolClone->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape, screen );
946 maxBleed = layerMaxBleed > maxBleed ? layerMaxBleed : maxBleed;
956 painter.begin( &picture );
957 painter.setRenderHint( QPainter::Antialiasing );
965 QgsSymbolRenderContext symbolContext( renderContext, units, 1.0,
false, Qgis::SymbolRenderHints(),
nullptr );
967 switch ( parentSymbolType )
982 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
983 layerClone->drawPreviewIcon( symbolContext, size );
991 QPixmap pixmap( size * devicePixelRatio );
992 pixmap.setDevicePixelRatio( devicePixelRatio );
993 pixmap.fill( Qt::transparent );
995 painter.begin( &pixmap );
996 painter.setRenderHint( QPainter::Antialiasing );
1012 QgsSymbolRenderContext symbolContext( renderContext, u, 1.0,
false, Qgis::SymbolRenderHints(),
nullptr );
1014 switch ( parentSymbolType )
1029 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
1030 layerClone->drawPreviewIcon( symbolContext, size );
1032 return QIcon( pixmap );
1042 QPixmap pixmap( size );
1043 pixmap.fill( Qt::transparent );
1046 painter.begin( &pixmap );
1049 if ( drawTransparentBackground )
1050 drawStippledBackground( &painter, QRect( padding, padding, size.width() - padding * 2, size.height() - padding * 2 ) );
1054 switch ( direction )
1056 case Qt::Horizontal:
1058 for (
int i = 0; i < size.width(); i++ )
1060 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.width() ) );
1061 painter.setPen( pen );
1062 const int x = flipDirection ? size.width() - i - 1 : i;
1063 painter.drawLine( x, 0 + padding, x, size.height() - 1 - padding );
1070 for (
int i = 0; i < size.height(); i++ )
1072 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.height() ) );
1073 painter.setPen( pen );
1074 const int y = flipDirection ? size.height() - i - 1 : i;
1075 painter.drawLine( 0 + padding, y, size.width() - 1 - padding, y );
1088 uchar pixDataRGB[] = { 255, 255, 255, 255,
1093 const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
1095 const int width = ( rect.width() < rect.height() ) ?
1096 rect.width() / 2.5 : rect.height() / 2.5;
1097 const QPixmap pix = QPixmap::fromImage( img.scaled( width, width ) );
1100 brush.setTexture( pix );
1101 painter->fillRect( rect, brush );
1106 const qreal s = ( markerSize - 1 ) / 2.0;
1111 p.setPen( QColor( 50, 100, 120, 200 ) );
1112 p.setBrush( QColor( 200, 200, 210, 120 ) );
1113 p.drawEllipse( x - s, y - s, s * 2, s * 2 );
1116 p.setPen( QColor( 255, 0, 0 ) );
1117 p.drawLine( x - s, y + s, x + s, y - s );
1118 p.drawLine( x - s, y - s, x + s, y + s );
1130static QPolygonF makeOffsetGeometry(
const QgsPolylineXY &polyline )
1132 int i, pointCount = polyline.count();
1134 QPolygonF resultLine;
1135 resultLine.resize( pointCount );
1139 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1140 resultLine[i] = QPointF( tempPtr->
x(), tempPtr->
y() );
1144static QList<QPolygonF> makeOffsetGeometry(
const QgsPolygonXY &polygon )
1146 QList<QPolygonF> resultGeom;
1147 resultGeom.reserve( polygon.size() );
1148 for (
int ring = 0; ring < polygon.size(); ++ring )
1149 resultGeom.append( makeOffsetGeometry( polygon[ ring ] ) );
1155 QList<QPolygonF> resultLine;
1157 if ( polyline.count() < 2 )
1159 resultLine.append( polyline );
1163 unsigned int i, pointCount = polyline.count();
1166 QPointF *tempPtr = polyline.data();
1167 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1168 tempPolyline[i] =
QgsPointXY( tempPtr->rx(), tempPtr->ry() );
1171 if ( !tempGeometry.
isNull() )
1173 const int quadSegments = 0;
1174 const double miterLimit = 2.0;
1182 if ( !offsetGeom.
isNull() )
1184 tempGeometry = offsetGeom;
1189 resultLine.append( makeOffsetGeometry( line ) );
1194 resultLine.append( makeOffsetGeometry( tempGeometry.
asPolygon() ) );
1200 resultLine.reserve( tempMPolyline.count() );
1201 for (
int part = 0; part < tempMPolyline.count(); ++part )
1203 resultLine.append( makeOffsetGeometry( tempMPolyline[ part ] ) );
1210 resultLine.reserve( tempMPolygon.count() );
1211 for (
int part = 0; part < tempMPolygon.count(); ++part )
1213 resultLine.append( makeOffsetGeometry( tempMPolygon[ part ] ) );
1221 resultLine.append( polyline );
1230 if ( element.isNull() )
1234 QDomNode layerNode = element.firstChild();
1236 while ( !layerNode.isNull() )
1238 QDomElement e = layerNode.toElement();
1239 if ( !e.isNull() && e.tagName() != QLatin1String(
"data_defined_properties" ) )
1241 if ( e.tagName() != QLatin1String(
"layer" ) )
1250 const QDomElement s = e.firstChildElement( QStringLiteral(
"symbol" ) );
1253 std::unique_ptr< QgsSymbol > subSymbol(
loadSymbol( s, context ) );
1260 layers.append( layer );
1262 for (
int i = 0; i < subSymbol->symbolLayerCount(); ++i )
1264 layers.append( subSymbol->symbolLayer( i )->clone() );
1269 const bool res = layer->setSubSymbol( subSymbol.release() );
1272 QgsDebugError( QStringLiteral(
"symbol layer refused subsymbol: " ) + s.attribute(
"name" ) );
1274 layers.append( layer );
1279 layers.append( layer );
1284 layerNode = layerNode.nextSibling();
1287 if ( layers.isEmpty() )
1293 const QString symbolType = element.attribute( QStringLiteral(
"type" ) );
1296 if ( symbolType == QLatin1String(
"line" ) )
1298 else if ( symbolType == QLatin1String(
"fill" ) )
1300 else if ( symbolType == QLatin1String(
"marker" ) )
1308 if ( element.hasAttribute( QStringLiteral(
"outputUnit" ) ) )
1312 if ( element.hasAttribute( ( QStringLiteral(
"mapUnitScale" ) ) ) )
1315 const double oldMin = element.attribute( QStringLiteral(
"mapUnitMinScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1316 mapUnitScale.
minScale = oldMin != 0 ? 1.0 / oldMin : 0;
1317 const double oldMax = element.attribute( QStringLiteral(
"mapUnitMaxScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1318 mapUnitScale.
maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
1321 symbol->
setOpacity( element.attribute( QStringLiteral(
"alpha" ), QStringLiteral(
"1.0" ) ).toDouble() );
1322 symbol->
setClipFeaturesToExtent( element.attribute( QStringLiteral(
"clip_to_extent" ), QStringLiteral(
"1" ) ).toInt() );
1323 symbol->
setForceRHR( element.attribute( QStringLiteral(
"force_rhr" ), QStringLiteral(
"0" ) ).toInt() );
1324 Qgis::SymbolFlags flags;
1325 if ( element.attribute( QStringLiteral(
"renderer_should_use_levels" ), QStringLiteral(
"0" ) ).toInt() )
1332 const QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1333 if ( !ddProps.isNull() )
1343 const QString layerClass = element.attribute( QStringLiteral(
"class" ) );
1344 const bool locked = element.attribute( QStringLiteral(
"locked" ) ).toInt();
1345 const bool enabled = element.attribute( QStringLiteral(
"enabled" ), QStringLiteral(
"1" ) ).toInt();
1346 const int pass = element.attribute( QStringLiteral(
"pass" ) ).toInt();
1347 const QString
id = element.attribute( QStringLiteral(
"id" ) );
1348 const Qgis::SymbolLayerUserFlags userFlags =
qgsFlagKeysToValue( element.attribute( QStringLiteral(
"userFlags" ) ), Qgis::SymbolLayerUserFlags() );
1368 if ( !
id.isEmpty() )
1372 const QDomElement effectElem = element.firstChildElement( QStringLiteral(
"effect" ) );
1373 if ( !effectElem.isNull() )
1381 const QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1382 if ( !ddProps.isNull() )
1389 const QSet< int > oldKeys = prevProperties.
propertyKeys();
1390 for (
int key : oldKeys )
1411 return QStringLiteral(
"line" );
1413 return QStringLiteral(
"marker" );
1415 return QStringLiteral(
"fill" );
1424 QDomElement symEl = doc.createElement( QStringLiteral(
"symbol" ) );
1425 symEl.setAttribute( QStringLiteral(
"type" ), _nameForSymbolType( symbol->
type() ) );
1426 symEl.setAttribute( QStringLiteral(
"name" ), name );
1427 symEl.setAttribute( QStringLiteral(
"alpha" ), QString::number( symbol->
opacity() ) );
1428 symEl.setAttribute( QStringLiteral(
"clip_to_extent" ), symbol->
clipFeaturesToExtent() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1429 symEl.setAttribute( QStringLiteral(
"force_rhr" ), symbol->
forceRHR() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1431 symEl.setAttribute( QStringLiteral(
"renderer_should_use_levels" ), QStringLiteral(
"1" ) );
1433 symEl.setAttribute( QStringLiteral(
"is_animated" ), symbol->
animationSettings().
isAnimated() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1438 QDomElement ddProps = doc.createElement( QStringLiteral(
"data_defined_properties" ) );
1440 symEl.appendChild( ddProps );
1446 QDomElement layerEl = doc.createElement( QStringLiteral(
"layer" ) );
1447 layerEl.setAttribute( QStringLiteral(
"class" ), layer->
layerType() );
1448 layerEl.setAttribute( QStringLiteral(
"enabled" ), layer->
enabled() );
1449 layerEl.setAttribute( QStringLiteral(
"locked" ), layer->
isLocked() );
1450 layerEl.setAttribute( QStringLiteral(
"pass" ), layer->
renderingPass() );
1451 layerEl.setAttribute( QStringLiteral(
"id" ), layer->
id() );
1452 if ( layer->
userFlags() != Qgis::SymbolLayerUserFlags() )
1465 QDomElement ddProps = doc.createElement( QStringLiteral(
"data_defined_properties" ) );
1467 layerEl.appendChild( ddProps );
1471 const QString subname = QStringLiteral(
"@%1@%2" ).arg( name ).arg( i );
1472 const QDomElement subEl =
saveSymbol( subname, subSymbol, doc, context );
1473 layerEl.appendChild( subEl );
1475 symEl.appendChild( layerEl );
1483 QDomDocument doc( QStringLiteral(
"qgis-symbol-definition" ) );
1486 QTextStream stream( &props );
1487 symbolElem.save( stream, -1 );
1493 QList<QgsSymbolLayer *> &layers )
1497 if ( element.isNull() )
1502 const QString symbolizerName = element.localName();
1504 if ( symbolizerName == QLatin1String(
"PointSymbolizer" ) )
1507 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1508 if ( graphicElem.isNull() )
1510 QgsDebugError( QStringLiteral(
"Graphic element not found in PointSymbolizer" ) );
1546 if ( symbolizerName == QLatin1String(
"LineSymbolizer" ) )
1549 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1550 if ( strokeElem.isNull() )
1552 QgsDebugError( QStringLiteral(
"Stroke element not found in LineSymbolizer" ) );
1582 if ( symbolizerName == QLatin1String(
"PolygonSymbolizer" ) )
1585 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1586 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1587 if ( fillElem.isNull() && strokeElem.isNull() )
1589 QgsDebugError( QStringLiteral(
"neither Fill nor Stroke element not found in PolygonSymbolizer" ) );
1607 if ( l->
layerType() == QLatin1String(
"SimpleFill" ) || l->
layerType() == QLatin1String(
"SVGFill" ) )
1643 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1644 if ( fillElem.isNull() )
1646 QgsDebugError( QStringLiteral(
"Fill element not found" ) );
1668 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1669 if ( strokeElem.isNull() )
1671 QgsDebugError( QStringLiteral(
"Stroke element not found" ) );
1687 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1688 if ( graphicElem.isNull() )
1690 QgsDebugError( QStringLiteral(
"Graphic element not found" ) );
1715 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1716 if ( graphicElem.isNull() )
1719 const QDomElement externalGraphicElem = graphicElem.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
1720 if ( externalGraphicElem.isNull() )
1724 const QDomElement formatElem = externalGraphicElem.firstChildElement( QStringLiteral(
"Format" ) );
1725 if ( formatElem.isNull() )
1728 const QString elementFormat = formatElem.firstChild().nodeValue();
1729 if ( ! format.isEmpty() && elementFormat != format )
1731 QgsDebugMsgLevel(
"unsupported External Graphic format found: " + elementFormat, 4 );
1736 const QDomElement onlineResourceElem = externalGraphicElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1737 const QDomElement inlineContentElem = externalGraphicElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1738 if ( !onlineResourceElem.isNull() )
1743 else if ( !inlineContentElem.isNull() )
1756 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1757 if ( graphicElem.isNull() )
1760 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1761 if ( markElem.isNull() )
1764 const QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
1765 return !wellKnownNameElem.isNull();
1771 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1772 if ( graphicElem.isNull() )
1775 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1776 if ( markElem.isNull() )
1780 const QDomElement formatElem = markElem.firstChildElement( QStringLiteral(
"Format" ) );
1781 if ( formatElem.isNull() )
1784 const QString format = formatElem.firstChild().nodeValue();
1785 if ( format != QLatin1String(
"ttf" ) )
1787 QgsDebugError(
"unsupported Graphic Mark format found: " + format );
1792 const QDomElement onlineResourceElem = markElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1793 const QDomElement inlineContentElem = markElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1794 if ( !onlineResourceElem.isNull() )
1797 const QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
1798 if ( !markIndexElem.isNull() )
1801 else if ( !inlineContentElem.isNull() )
1816 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1817 if ( graphicElem.isNull() )
1821 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
1823 if ( it.key() == QLatin1String(
"widthHeightFactor" ) )
1834 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1835 if ( strokeElem.isNull() )
1838 QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral(
"GraphicStroke" ) );
1839 if ( graphicStrokeElem.isNull() )
1847 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1848 if ( fillElem.isNull() )
1851 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1852 if ( graphicFillElem.isNull() )
1855 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1856 if ( graphicElem.isNull() )
1862 QColor fillColor, strokeColor;
1863 double size, strokeWidth;
1864 Qt::PenStyle strokeStyle;
1865 if ( !
wellKnownMarkerFromSld( graphicElem, name, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
1868 if ( name != QLatin1String(
"horline" ) )
1876 const double angle = angleFunc.toDouble( &ok );
1882 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1883 if ( fillElem.isNull() )
1886 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1887 if ( graphicFillElem.isNull() )
1890 const QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1891 if ( graphicElem.isNull() )
1894 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1895 if ( markElem.isNull() )
1903 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1904 if ( fillElem.isNull() )
1907 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1908 if ( graphicFillElem.isNull() )
1916 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1917 if ( fillElem.isNull() )
1920 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1921 if ( graphicFillElem.isNull() )
1941 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1942 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1946 bool validFill =
false, validStroke =
false;
1951 Qt::BrushStyle fillStyle;
1953 if (
fillFromSld( fillElem, fillStyle, fillColor ) )
1959 Qt::PenStyle strokeStyle;
1960 double strokeWidth = 1.0, dashOffset = 0.0;
1961 QVector<qreal> customDashPattern;
1963 if (
lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth,
1964 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
1967 if ( validFill || validStroke )
1970 map[QStringLiteral(
"name" )] = QStringLiteral(
"square" );
1973 map[QStringLiteral(
"size" )] = QString::number( 6 );
1974 map[QStringLiteral(
"angle" )] = QString::number( 0 );
1975 map[QStringLiteral(
"offset" )] =
encodePoint( QPointF( 0, 0 ) );
1982 bool validFill =
false, validStroke =
false;
1985 QString name, format;
1987 QColor fillColor, strokeColor;
1988 double strokeWidth = 1.0, size = 0.0, angle = 0.0;
1992 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1993 if ( !graphicFillElem.isNull() )
1996 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1997 if ( !graphicElem.isNull() )
2003 const QDomElement graphicChildElem = graphicElem.firstChildElement();
2004 while ( !graphicChildElem.isNull() )
2006 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2009 const QDomElement wellKnownNameElem = graphicChildElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
2010 if ( !wellKnownNameElem.isNull() )
2012 name = wellKnownNameElem.firstChild().nodeValue();
2018 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) || graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2021 const QDomElement formatElem = graphicChildElem.firstChildElement( QStringLiteral(
"Format" ) );
2022 if ( formatElem.isNull() )
2025 format = formatElem.firstChild().nodeValue();
2029 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) && format != QLatin1String(
"image/svg+xml" ) )
2034 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format != QLatin1String(
"ttf" ) )
2038 const QDomElement onlineResourceElem = graphicChildElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
2039 const QDomElement inlineContentElem = graphicChildElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
2041 if ( !onlineResourceElem.isNull() )
2043 name = onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) );
2045 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format == QLatin1String(
"ttf" ) )
2048 if ( name.startsWith( QLatin1String(
"ttf://" ) ) )
2049 name = name.mid( 6 );
2052 const QDomElement markIndexElem = graphicChildElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
2053 if ( markIndexElem.isNull() )
2057 const int v = markIndexElem.firstChild().nodeValue().toInt( &ok );
2068 else if ( !inlineContentElem.isNull() )
2078 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2080 name = QStringLiteral(
"square" );
2087 if ( found && graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2094 Qt::BrushStyle markFillStyle;
2096 QDomElement markFillElem = graphicChildElem.firstChildElement( QStringLiteral(
"Fill" ) );
2097 if (
fillFromSld( markFillElem, markFillStyle, fillColor ) )
2102 Qt::PenStyle strokeStyle;
2103 double strokeWidth = 1.0, dashOffset = 0.0;
2104 QVector<qreal> customDashPattern;
2106 QDomElement markStrokeElem = graphicChildElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2107 if (
lineFromSld( markStrokeElem, strokeStyle, strokeColor, strokeWidth,
2108 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2115 const QDomElement opacityElem = graphicElem.firstChildElement( QStringLiteral(
"Opacity" ) );
2116 if ( !opacityElem.isNull() )
2117 fillColor.setAlpha(
decodeSldAlpha( opacityElem.firstChild().nodeValue() ) );
2119 const QDomElement sizeElem = graphicElem.firstChildElement( QStringLiteral(
"Size" ) );
2120 if ( !sizeElem.isNull() )
2123 const double v = sizeElem.firstChild().nodeValue().toDouble( &ok );
2132 const double v = angleFunc.toDouble( &ok );
2142 if ( validFill || validStroke )
2144 if ( format == QLatin1String(
"image/svg+xml" ) )
2147 map[QStringLiteral(
"name" )] = name;
2148 map[QStringLiteral(
"fill" )] = fillColor.name();
2149 map[QStringLiteral(
"outline" )] = strokeColor.name();
2150 map[QStringLiteral(
"outline-width" )] = QString::number( strokeWidth );
2152 map[QStringLiteral(
"size" )] = QString::number( size );
2154 map[QStringLiteral(
"angle" )] = QString::number( angle );
2155 if ( !offset.isNull() )
2156 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
2159 else if ( format == QLatin1String(
"ttf" ) )
2162 map[QStringLiteral(
"font" )] = name;
2163 map[QStringLiteral(
"chr" )] = markIndex;
2166 map[QStringLiteral(
"size" )] = QString::number( size );
2168 map[QStringLiteral(
"angle" )] = QString::number( angle );
2169 if ( !offset.isNull() )
2170 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
2176 if ( layers.isEmpty() )
2179 layerList << layers;
2186 QString patternName;
2187 switch ( brushStyle )
2192 case Qt::SolidPattern:
2193 if ( color.isValid() )
2196 if ( color.alpha() < 255 )
2201 case Qt::CrossPattern:
2202 case Qt::DiagCrossPattern:
2203 case Qt::HorPattern:
2204 case Qt::VerPattern:
2205 case Qt::BDiagPattern:
2206 case Qt::FDiagPattern:
2207 case Qt::Dense1Pattern:
2208 case Qt::Dense2Pattern:
2209 case Qt::Dense3Pattern:
2210 case Qt::Dense4Pattern:
2211 case Qt::Dense5Pattern:
2212 case Qt::Dense6Pattern:
2213 case Qt::Dense7Pattern:
2218 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( brushStyle ) ) );
2222 QDomElement graphicFillElem = doc.createElement( QStringLiteral(
"se:GraphicFill" ) );
2223 element.appendChild( graphicFillElem );
2225 QDomElement graphicElem = doc.createElement( QStringLiteral(
"se:Graphic" ) );
2226 graphicFillElem.appendChild( graphicElem );
2228 const QColor fillColor = patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
2229 const QColor strokeColor = !patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
2232 wellKnownMarkerToSld( doc, graphicElem, patternName, fillColor, strokeColor, Qt::SolidLine, -1, -1 );
2239 brushStyle = Qt::SolidPattern;
2240 color = QColor( 128, 128, 128 );
2242 if ( element.isNull() )
2244 brushStyle = Qt::NoBrush;
2249 const QDomElement graphicFillElem = element.firstChildElement( QStringLiteral(
"GraphicFill" ) );
2251 if ( graphicFillElem.isNull() )
2254 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2256 QgsDebugMsgLevel( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ), 2 );
2258 if ( it.key() == QLatin1String(
"fill" ) )
2259 color = QColor( it.value() );
2260 else if ( it.key() == QLatin1String(
"fill-opacity" ) )
2266 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
2267 if ( graphicElem.isNull() )
2270 QString patternName = QStringLiteral(
"square" );
2271 QColor fillColor, strokeColor;
2272 double strokeWidth, size;
2273 Qt::PenStyle strokeStyle;
2274 if ( !
wellKnownMarkerFromSld( graphicElem, patternName, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
2278 if ( brushStyle == Qt::NoBrush )
2281 const QColor
c = patternName.startsWith( QLatin1String(
"brush://" ) ) ? fillColor : strokeColor;
2290 Qt::PenStyle penStyle,
const QColor &color,
double width,
2291 const Qt::PenJoinStyle *penJoinStyle,
const Qt::PenCapStyle *penCapStyle,
2292 const QVector<qreal> *customDashPattern,
double dashOffset )
2294 QVector<qreal> dashPattern;
2295 const QVector<qreal> *pattern = &dashPattern;
2297 if ( penStyle == Qt::CustomDashLine && !customDashPattern )
2299 element.appendChild( doc.createComment( QStringLiteral(
"WARNING: Custom dash pattern required but not provided. Using default dash pattern." ) ) );
2300 penStyle = Qt::DashLine;
2312 dashPattern.push_back( 4.0 );
2313 dashPattern.push_back( 2.0 );
2316 dashPattern.push_back( 1.0 );
2317 dashPattern.push_back( 2.0 );
2319 case Qt::DashDotLine:
2320 dashPattern.push_back( 4.0 );
2321 dashPattern.push_back( 2.0 );
2322 dashPattern.push_back( 1.0 );
2323 dashPattern.push_back( 2.0 );
2325 case Qt::DashDotDotLine:
2326 dashPattern.push_back( 4.0 );
2327 dashPattern.push_back( 2.0 );
2328 dashPattern.push_back( 1.0 );
2329 dashPattern.push_back( 2.0 );
2330 dashPattern.push_back( 1.0 );
2331 dashPattern.push_back( 2.0 );
2334 case Qt::CustomDashLine:
2335 Q_ASSERT( customDashPattern );
2336 pattern = customDashPattern;
2340 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( penStyle ) ) );
2344 if ( color.isValid() )
2347 if ( color.alpha() < 255 )
2354 else if ( width == 0 )
2364 if ( !pattern->isEmpty() )
2374 Qt::PenStyle &penStyle, QColor &color,
double &width,
2375 Qt::PenJoinStyle *penJoinStyle, Qt::PenCapStyle *penCapStyle,
2376 QVector<qreal> *customDashPattern,
double *dashOffset )
2380 penStyle = Qt::SolidLine;
2381 color = QColor( 0, 0, 0 );
2384 *penJoinStyle = Qt::BevelJoin;
2386 *penCapStyle = Qt::SquareCap;
2387 if ( customDashPattern )
2388 customDashPattern->clear();
2392 if ( element.isNull() )
2394 penStyle = Qt::NoPen;
2400 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2402 QgsDebugMsgLevel( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ), 2 );
2404 if ( it.key() == QLatin1String(
"stroke" ) )
2406 color = QColor( it.value() );
2408 else if ( it.key() == QLatin1String(
"stroke-opacity" ) )
2412 else if ( it.key() == QLatin1String(
"stroke-width" ) )
2415 const double w = it.value().toDouble( &ok );
2419 else if ( it.key() == QLatin1String(
"stroke-linejoin" ) && penJoinStyle )
2423 else if ( it.key() == QLatin1String(
"stroke-linecap" ) && penCapStyle )
2427 else if ( it.key() == QLatin1String(
"stroke-dasharray" ) )
2430 if ( !dashPattern.isEmpty() )
2434 bool dashPatternFound =
false;
2436 if ( dashPattern.count() == 2 )
2438 if ( dashPattern.at( 0 ) == 4.0 &&
2439 dashPattern.at( 1 ) == 2.0 )
2441 penStyle = Qt::DashLine;
2442 dashPatternFound =
true;
2444 else if ( dashPattern.at( 0 ) == 1.0 &&
2445 dashPattern.at( 1 ) == 2.0 )
2447 penStyle = Qt::DotLine;
2448 dashPatternFound =
true;
2451 else if ( dashPattern.count() == 4 )
2453 if ( dashPattern.at( 0 ) == 4.0 &&
2454 dashPattern.at( 1 ) == 2.0 &&
2455 dashPattern.at( 2 ) == 1.0 &&
2456 dashPattern.at( 3 ) == 2.0 )
2458 penStyle = Qt::DashDotLine;
2459 dashPatternFound =
true;
2462 else if ( dashPattern.count() == 6 )
2464 if ( dashPattern.at( 0 ) == 4.0 &&
2465 dashPattern.at( 1 ) == 2.0 &&
2466 dashPattern.at( 2 ) == 1.0 &&
2467 dashPattern.at( 3 ) == 2.0 &&
2468 dashPattern.at( 4 ) == 1.0 &&
2469 dashPattern.at( 5 ) == 2.0 )
2471 penStyle = Qt::DashDotDotLine;
2472 dashPatternFound =
true;
2477 if ( !dashPatternFound )
2479 if ( customDashPattern )
2481 penStyle = Qt::CustomDashLine;
2482 *customDashPattern = dashPattern;
2486 QgsDebugMsgLevel( QStringLiteral(
"custom dash pattern required but not provided. Using default dash pattern." ), 2 );
2487 penStyle = Qt::DashLine;
2492 else if ( it.key() == QLatin1String(
"stroke-dashoffset" ) && dashOffset )
2495 const double d = it.value().toDouble( &ok );
2505 const QString &path,
const QString &mime,
2506 const QColor &color,
double size )
2508 QDomElement externalGraphicElem = doc.createElement( QStringLiteral(
"se:ExternalGraphic" ) );
2509 element.appendChild( externalGraphicElem );
2518 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2520 element.appendChild( sizeElem );
2525 const QString &path,
const QColor &fillColor,
double size,
const QColor &strokeColor,
double strokeWidth )
2532 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Parametric SVG" ) ) );
2533 const QString parametricPath =
getSvgParametricPath( path, fillColor, strokeColor, strokeWidth );
2536 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Plain SVG fallback, no parameters" ) ) );
2539 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Well known marker fallback" ) ) );
2545 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2547 graphicElem.appendChild( sizeElem );
2555 if ( fillColor.isValid() )
2557 url.addQueryItem( QStringLiteral(
"fill" ), fillColor.name() );
2558 url.addQueryItem( QStringLiteral(
"fill-opacity" ),
encodeSldAlpha( fillColor.alpha() ) );
2562 url.addQueryItem( QStringLiteral(
"fill" ), QStringLiteral(
"#000000" ) );
2563 url.addQueryItem( QStringLiteral(
"fill-opacity" ), QStringLiteral(
"1" ) );
2565 if ( strokeColor.isValid() )
2567 url.addQueryItem( QStringLiteral(
"outline" ), strokeColor.name() );
2568 url.addQueryItem( QStringLiteral(
"outline-opacity" ),
encodeSldAlpha( strokeColor.alpha() ) );
2572 url.addQueryItem( QStringLiteral(
"outline" ), QStringLiteral(
"#000000" ) );
2573 url.addQueryItem( QStringLiteral(
"outline-opacity" ), QStringLiteral(
"1" ) );
2575 url.addQueryItem( QStringLiteral(
"outline-width" ), QString::number( strokeWidth ) );
2576 const QString params = url.toString( QUrl::FullyEncoded );
2577 if ( params.isEmpty() )
2583 return basePath +
"?" + params;
2588 QString &path, QString &mime,
2589 QColor &color,
double &size )
2594 QDomElement externalGraphicElem = element.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
2595 if ( externalGraphicElem.isNull() )
2600 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2601 if ( !sizeElem.isNull() )
2604 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2613 const QString &path,
const QString &format,
int *markIndex,
2614 const QColor &color,
double size )
2616 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2617 element.appendChild( markElem );
2623 QDomElement markIndexElem = doc.createElement( QStringLiteral(
"se:MarkIndex" ) );
2624 markIndexElem.appendChild( doc.createTextNode( QString::number( *markIndex ) ) );
2625 markElem.appendChild( markIndexElem );
2629 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2630 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2631 markElem.appendChild( fillElem );
2636 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2638 element.appendChild( sizeElem );
2643 QString &path, QString &format,
int &markIndex,
2644 QColor &color,
double &size )
2652 QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2653 if ( markElem.isNull() )
2658 const QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
2659 if ( !markIndexElem.isNull() )
2662 const int i = markIndexElem.firstChild().nodeValue().toInt( &ok );
2668 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2669 Qt::BrushStyle b = Qt::SolidPattern;
2674 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2675 if ( !sizeElem.isNull() )
2678 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2687 const QString &name,
const QColor &color,
const QColor &strokeColor, Qt::PenStyle strokeStyle,
2688 double strokeWidth,
double size )
2690 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2691 element.appendChild( markElem );
2693 QDomElement wellKnownNameElem = doc.createElement( QStringLiteral(
"se:WellKnownName" ) );
2694 wellKnownNameElem.appendChild( doc.createTextNode( name ) );
2695 markElem.appendChild( wellKnownNameElem );
2698 if ( color.isValid() )
2700 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2701 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2702 markElem.appendChild( fillElem );
2706 if ( strokeColor.isValid() )
2708 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
2709 lineToSld( doc, strokeElem, strokeStyle, strokeColor, strokeWidth );
2710 markElem.appendChild( strokeElem );
2716 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2718 element.appendChild( sizeElem );
2723 QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle,
2724 double &strokeWidth,
double &size )
2728 name = QStringLiteral(
"square" );
2730 strokeColor = QColor( 0, 0, 0 );
2734 const QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2735 if ( markElem.isNull() )
2738 const QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
2739 if ( !wellKnownNameElem.isNull() )
2741 name = wellKnownNameElem.firstChild().nodeValue();
2746 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2747 Qt::BrushStyle b = Qt::SolidPattern;
2752 QDomElement strokeElem = markElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2753 lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth );
2757 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2758 if ( !sizeElem.isNull() )
2761 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2771 if ( !rotationFunc.isEmpty() )
2773 QDomElement rotationElem = doc.createElement( QStringLiteral(
"se:Rotation" ) );
2775 element.appendChild( rotationElem );
2781 QDomElement rotationElem = element.firstChildElement( QStringLiteral(
"Rotation" ) );
2782 if ( !rotationElem.isNull() )
2792 if ( !alphaFunc.isEmpty() )
2794 QDomElement opacityElem = doc.createElement( QStringLiteral(
"se:Opacity" ) );
2796 element.appendChild( opacityElem );
2802 QDomElement opacityElem = element.firstChildElement( QStringLiteral(
"Opacity" ) );
2803 if ( !opacityElem.isNull() )
2812 if ( offset.isNull() )
2815 QDomElement displacementElem = doc.createElement( QStringLiteral(
"se:Displacement" ) );
2816 element.appendChild( displacementElem );
2818 QDomElement dispXElem = doc.createElement( QStringLiteral(
"se:DisplacementX" ) );
2819 dispXElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.x(), 2 ) ) );
2821 QDomElement dispYElem = doc.createElement( QStringLiteral(
"se:DisplacementY" ) );
2822 dispYElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.y(), 2 ) ) );
2824 displacementElem.appendChild( dispXElem );
2825 displacementElem.appendChild( dispYElem );
2832 QDomElement anchorElem = doc.createElement( QStringLiteral(
"se:AnchorPoint" ) );
2833 element.appendChild( anchorElem );
2835 QDomElement anchorXElem = doc.createElement( QStringLiteral(
"se:AnchorPointX" ) );
2836 anchorXElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.x() ) ) );
2838 QDomElement anchorYElem = doc.createElement( QStringLiteral(
"se:AnchorPointY" ) );
2839 anchorYElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.y() ) ) );
2841 anchorElem.appendChild( anchorXElem );
2842 anchorElem.appendChild( anchorYElem );
2847 offset = QPointF( 0, 0 );
2849 const QDomElement displacementElem = element.firstChildElement( QStringLiteral(
"Displacement" ) );
2850 if ( displacementElem.isNull() )
2853 const QDomElement dispXElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementX" ) );
2854 if ( !dispXElem.isNull() )
2857 const double offsetX = dispXElem.firstChild().nodeValue().toDouble( &ok );
2859 offset.setX( offsetX );
2862 const QDomElement dispYElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementY" ) );
2863 if ( !dispYElem.isNull() )
2866 const double offsetY = dispYElem.firstChild().nodeValue().toDouble( &ok );
2868 offset.setY( offsetY );
2875 const QString &label,
const QFont &font,
2876 const QColor &color,
double size )
2878 QDomElement labelElem = doc.createElement( QStringLiteral(
"se:Label" ) );
2879 labelElem.appendChild( doc.createTextNode( label ) );
2880 element.appendChild( labelElem );
2882 QDomElement fontElem = doc.createElement( QStringLiteral(
"se:Font" ) );
2883 element.appendChild( fontElem );
2887 fontElem.appendChild( createSldParameterElement( doc,
"font-style",
encodeSldFontStyle( font.style() ) ) );
2888 fontElem.appendChild( createSldParameterElement( doc,
"font-weight",
encodeSldFontWeight( font.weight() ) ) );
2893 if ( color.isValid() )
2895 QDomElement fillElem = doc.createElement( QStringLiteral(
"Fill" ) );
2896 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2897 element.appendChild( fillElem );
2902 Qt::PenJoinStyle joinStyle,
2903 Qt::PenCapStyle capStyle,
2905 const QVector<qreal> *dashPattern )
2908 penStyle.append(
"PEN(" );
2909 penStyle.append(
"c:" );
2910 penStyle.append(
c.name() );
2911 penStyle.append(
",w:" );
2913 penStyle.append( QString::number( width * mmScaleFactor ) );
2914 penStyle.append(
"mm" );
2917 if ( dashPattern && !dashPattern->isEmpty() )
2919 penStyle.append(
",p:\"" );
2920 QVector<qreal>::const_iterator pIt = dashPattern->constBegin();
2921 for ( ; pIt != dashPattern->constEnd(); ++pIt )
2923 if ( pIt != dashPattern->constBegin() )
2925 penStyle.append(
' ' );
2927 penStyle.append( QString::number( *pIt * mapUnitScaleFactor ) );
2928 penStyle.append(
'g' );
2930 penStyle.append(
'\"' );
2934 penStyle.append(
",cap:" );
2938 penStyle.append(
'p' );
2941 penStyle.append(
'r' );
2945 penStyle.append(
'b' );
2949 penStyle.append(
",j:" );
2950 switch ( joinStyle )
2953 penStyle.append(
'b' );
2956 penStyle.append(
'r' );
2960 penStyle.append(
'm' );
2966 penStyle.append(
",dp:" );
2967 penStyle.append( QString::number( offset * mapUnitScaleFactor ) );
2968 penStyle.append(
'g' );
2971 penStyle.append(
')' );
2978 brushStyle.append(
"BRUSH(" );
2979 brushStyle.append(
"fc:" );
2980 brushStyle.append( fillColor.name() );
2981 brushStyle.append(
')' );
2987 if ( geomFunc.isEmpty() )
2990 QDomElement geometryElem = doc.createElement( QStringLiteral(
"Geometry" ) );
2991 element.appendChild( geometryElem );
3021 QDomElement geometryElem = element.firstChildElement( QStringLiteral(
"Geometry" ) );
3022 if ( geometryElem.isNull() )
3034 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " + function ) );
3038 if ( !filterElem.isNull() )
3039 element.appendChild( filterElem );
3047 if ( function == QLatin1String(
"ELSE" ) )
3050 element.appendChild( filterElem );
3059 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " + function ) );
3063 if ( !filterElem.isNull() )
3064 element.appendChild( filterElem );
3072 QDomElement elem = element;
3073 if ( element.tagName() != QLatin1String(
"Filter" ) )
3075 const QDomNodeList filterNodes = element.elementsByTagName( QStringLiteral(
"Filter" ) );
3076 if ( !filterNodes.isEmpty() )
3078 elem = filterNodes.at( 0 ).toElement();
3082 if ( elem.isNull() )
3107 const QString &path,
const QString &format )
3111 QDomElement onlineResourceElem = doc.createElement( QStringLiteral(
"se:OnlineResource" ) );
3112 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
3113 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:href" ), url );
3114 element.appendChild( onlineResourceElem );
3116 QDomElement formatElem = doc.createElement( QStringLiteral(
"se:Format" ) );
3117 formatElem.appendChild( doc.createTextNode( format ) );
3118 element.appendChild( formatElem );
3125 const QDomElement onlineResourceElem = element.firstChildElement( QStringLiteral(
"OnlineResource" ) );
3126 if ( onlineResourceElem.isNull() )
3129 path = QUrl::fromPercentEncoding( onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) ).toUtf8() );
3131 const QDomElement formatElem = element.firstChildElement( QStringLiteral(
"Format" ) );
3132 if ( formatElem.isNull() )
3135 format = formatElem.firstChild().nodeValue();
3142 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:SvgParameter" ) );
3143 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
3144 nodeElem.appendChild( doc.createTextNode( value ) );
3153 QDomElement paramElem = element.firstChildElement();
3154 while ( !paramElem.isNull() )
3156 if ( paramElem.localName() == QLatin1String(
"SvgParameter" ) || paramElem.localName() == QLatin1String(
"CssParameter" ) )
3158 const QString name = paramElem.attribute( QStringLiteral(
"name" ) );
3159 if ( paramElem.firstChild().nodeType() == QDomNode::TextNode )
3161 value = paramElem.firstChild().nodeValue();
3165 if ( paramElem.firstChild().nodeType() == QDomNode::ElementNode &&
3166 paramElem.firstChild().localName() == QLatin1String(
"Literal" ) )
3169 value = paramElem.firstChild().firstChild().nodeValue();
3173 QgsDebugError( QStringLiteral(
"unexpected child of %1" ).arg( paramElem.localName() ) );
3177 if ( !name.isEmpty() && !value.isEmpty() )
3178 params[ name ] = value;
3181 paramElem = paramElem.nextSiblingElement();
3189 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:VendorOption" ) );
3190 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
3191 nodeElem.appendChild( doc.createTextNode( value ) );
3199 QDomElement paramElem = element.firstChildElement( QStringLiteral(
"VendorOption" ) );
3200 while ( !paramElem.isNull() )
3202 const QString name = paramElem.attribute( QStringLiteral(
"name" ) );
3203 const QString value = paramElem.firstChild().nodeValue();
3205 if ( !name.isEmpty() && !value.isEmpty() )
3206 params[ name ] = value;
3208 paramElem = paramElem.nextSiblingElement( QStringLiteral(
"VendorOption" ) );
3218 if ( newSymbols.type() == QVariant::Map )
3220 return newSymbols.toMap();
3227 QDomElement e = element.firstChildElement();
3228 while ( !e.isNull() )
3230 if ( e.tagName() == QLatin1String(
"prop" ) )
3232 const QString propKey = e.attribute( QStringLiteral(
"k" ) );
3233 const QString propValue = e.attribute( QStringLiteral(
"v" ) );
3234 props[propKey] = propValue;
3236 e = e.nextSiblingElement();
3253 QDomElement e = element.firstChildElement();
3255 while ( !e.isNull() )
3257 if ( e.tagName() == QLatin1String(
"symbol" ) )
3261 symbols.insert( e.attribute( QStringLiteral(
"name" ) ), symbol );
3267 e = e.nextSiblingElement();
3274 QStringList subsymbols;
3276 for ( QMap<QString, QgsSymbol *>::iterator it = symbols.begin(); it != symbols.end(); ++it )
3278 if ( it.key()[0] !=
'@' )
3282 subsymbols.append( it.key() );
3284 QStringList parts = it.key().split(
'@' );
3285 if ( parts.count() < 3 )
3287 QgsDebugError(
"found subsymbol with invalid name: " + it.key() );
3291 const QString symname = parts[1];
3292 const int symlayer = parts[2].toInt();
3294 if ( !symbols.contains( symname ) )
3296 QgsDebugError(
"subsymbol references invalid symbol: " + symname );
3304 QgsDebugError(
"subsymbol references invalid symbol layer: " + QString::number( symlayer ) );
3313 QgsDebugError(
"symbol layer refused subsymbol: " + it.key() );
3320 for (
int i = 0; i < subsymbols.count(); i++ )
3321 symbols.take( subsymbols[i] );
3328 QDomElement symbolsElem = doc.createElement( tagName );
3331 for ( QMap<QString, QgsSymbol *>::iterator its = symbols.begin(); its != symbols.end(); ++its )
3333 const QDomElement symEl =
saveSymbol( its.key(), its.value(), doc, context );
3334 symbolsElem.appendChild( symEl );
3342 qDeleteAll( symbols );
3351 std::unique_ptr< QMimeData >mimeData(
new QMimeData );
3353 QDomDocument symbolDoc;
3355 symbolDoc.appendChild( symbolElem );
3356 mimeData->setText( symbolDoc.toString() );
3359 mimeData->setColorData( symbol->
color() );
3361 return mimeData.release();
3369 const QString text = data->text();
3370 if ( !text.isEmpty() )
3375 if ( doc.setContent( text ) )
3377 elem = doc.documentElement();
3379 if ( elem.nodeName() != QLatin1String(
"symbol" ) )
3380 elem = elem.firstChildElement( QStringLiteral(
"symbol" ) );
3391 const QString rampType = element.attribute( QStringLiteral(
"type" ) );
3416 QDomElement rampEl = doc.createElement( QStringLiteral(
"colorramp" ) );
3417 rampEl.setAttribute( QStringLiteral(
"type" ), ramp->
type() );
3418 rampEl.setAttribute( QStringLiteral(
"name" ), name );
3426 QVariantMap rampMap;
3428 rampMap.insert( QStringLiteral(
"type" ), ramp->
type() );
3429 rampMap.insert( QStringLiteral(
"name" ), name );
3431 const QVariantMap properties = ramp->
properties();
3433 QVariantMap propertyMap;
3434 for (
auto property = properties.constBegin();
property != properties.constEnd(); ++property )
3436 propertyMap.insert( property.key(),
property.value() );
3439 rampMap.insert( QStringLiteral(
"properties" ), propertyMap );
3445 const QVariantMap rampMap = value.toMap();
3447 const QString rampType = rampMap.
value( QStringLiteral(
"type" ) ).toString();
3450 const QVariantMap propertyMap = rampMap.value( QStringLiteral(
"properties" ) ).toMap();
3453 for (
auto property = propertyMap.constBegin();
property != propertyMap.constEnd(); ++property )
3455 props.insert( property.key(),
property.value().toString() );
3477 if ( !color.isValid() )
3484 return color.name();
3489 QList<QColor> colors;
3492 const thread_local QRegularExpression sepCommaSpaceRegExp(
"(,|\\s)" );
3493 QStringList components = colorStr.simplified().split( sepCommaSpaceRegExp );
3494 QStringList::iterator it = components.begin();
3495 for ( ; it != components.end(); ++it )
3497 const QColor result =
parseColor( *it,
true );
3498 if ( result.isValid() )
3503 if ( colors.length() > 0 )
3509 const thread_local QRegularExpression sepCommaRegExp(
"(,|\n)" );
3510 components = colorStr.split( sepCommaRegExp );
3511 it = components.begin();
3512 for ( ; it != components.end(); ++it )
3514 const QColor result =
parseColor( *it,
true );
3515 if ( result.isValid() )
3520 if ( colors.length() > 0 )
3526 components = colorStr.simplified().split( QString(
' ' ) );
3527 it = components.begin();
3528 for ( ; it != components.end(); ++it )
3530 const QColor result =
parseColor( *it,
true );
3531 if ( result.isValid() )
3536 if ( colors.length() > 0 )
3542 components = colorStr.split(
'\n' );
3543 it = components.begin();
3544 for ( ; it != components.end(); ++it )
3546 const QColor result =
parseColor( *it,
true );
3547 if ( result.isValid() )
3560 QMimeData *mimeData =
new QMimeData;
3561 mimeData->setColorData( QVariant( color ) );
3562 mimeData->setText( color.name() );
3569 if ( mimeData->hasColor() )
3571 QColor mimeColor = mimeData->colorData().value<QColor>();
3572 if ( mimeColor.isValid() )
3580 if ( mimeData->hasText() )
3584 if ( textColor.isValid() )
3599 if ( data->hasFormat( QStringLiteral(
"text/xml" ) ) )
3602 const QByteArray encodedData = data->data( QStringLiteral(
"text/xml" ) );
3603 QDomDocument xmlDoc;
3604 xmlDoc.setContent( encodedData );
3606 const QDomElement dragDataElem = xmlDoc.documentElement();
3607 if ( dragDataElem.tagName() == QLatin1String(
"ColorSchemeModelDragData" ) )
3609 const QDomNodeList nodeList = dragDataElem.childNodes();
3610 const int nChildNodes = nodeList.size();
3611 QDomElement currentElem;
3613 for (
int i = 0; i < nChildNodes; ++i )
3615 currentElem = nodeList.at( i ).toElement();
3616 if ( currentElem.isNull() )
3621 QPair< QColor, QString> namedColor;
3623 namedColor.second = currentElem.attribute( QStringLiteral(
"label" ), QString() );
3625 mimeColors << namedColor;
3630 if ( mimeColors.length() == 0 && data->hasFormat( QStringLiteral(
"application/x-colorobject-list" ) ) )
3633 const QByteArray encodedData = data->data( QStringLiteral(
"application/x-colorobject-list" ) );
3634 QDomDocument xmlDoc;
3635 xmlDoc.setContent( encodedData );
3637 const QDomNodeList colorsNodes = xmlDoc.elementsByTagName( QStringLiteral(
"colors" ) );
3638 if ( colorsNodes.length() > 0 )
3640 const QDomElement colorsElem = colorsNodes.at( 0 ).toElement();
3641 const QDomNodeList colorNodeList = colorsElem.childNodes();
3642 const int nChildNodes = colorNodeList.size();
3643 QDomElement currentElem;
3645 for (
int i = 0; i < nChildNodes; ++i )
3648 currentElem = colorNodeList.at( i ).toElement();
3649 if ( currentElem.isNull() )
3654 const QDomNodeList colorNodes = currentElem.elementsByTagName( QStringLiteral(
"color" ) );
3655 const QDomNodeList nameNodes = currentElem.elementsByTagName( QStringLiteral(
"name" ) );
3657 if ( colorNodes.length() > 0 )
3659 const QDomElement colorElem = colorNodes.at( 0 ).toElement();
3661 const QStringList colorParts = colorElem.text().simplified().split(
' ' );
3662 if ( colorParts.length() < 3 )
3667 const int red = colorParts.at( 0 ).toDouble() * 255;
3668 const int green = colorParts.at( 1 ).toDouble() * 255;
3669 const int blue = colorParts.at( 2 ).toDouble() * 255;
3670 QPair< QColor, QString> namedColor;
3671 namedColor.first = QColor( red, green, blue );
3672 if ( nameNodes.length() > 0 )
3674 const QDomElement nameElem = nameNodes.at( 0 ).toElement();
3675 namedColor.second = nameElem.text();
3677 mimeColors << namedColor;
3683 if ( mimeColors.length() == 0 && data->hasText() )
3687 QList< QColor >::iterator it = parsedColors.begin();
3688 for ( ; it != parsedColors.end(); ++it )
3690 mimeColors << qMakePair( *it, QString() );
3694 if ( mimeColors.length() == 0 && data->hasColor() )
3697 const QColor mimeColor = data->colorData().value<QColor>();
3698 if ( mimeColor.isValid() )
3700 mimeColors << qMakePair( mimeColor, QString() );
3710 QMimeData *mimeData =
new QMimeData();
3711 QDomDocument xmlDoc;
3712 QDomElement xmlRootElement = xmlDoc.createElement( QStringLiteral(
"ColorSchemeModelDragData" ) );
3713 xmlDoc.appendChild( xmlRootElement );
3715 QgsNamedColorList::const_iterator colorIt = colorList.constBegin();
3716 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3718 QDomElement namedColor = xmlDoc.createElement( QStringLiteral(
"NamedColor" ) );
3720 namedColor.setAttribute( QStringLiteral(
"label" ), ( *colorIt ).second );
3721 xmlRootElement.appendChild( namedColor );
3723 mimeData->setData( QStringLiteral(
"text/xml" ), xmlDoc.toByteArray() );
3731 colorIt = colorList.constBegin();
3732 QStringList colorListString;
3733 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3735 colorListString << ( *colorIt ).first.name();
3737 mimeData->setText( colorListString.join( QLatin1Char(
'\n' ) ) );
3740 if ( colorList.length() > 0 )
3742 mimeData->setColorData( QVariant( colorList.at( 0 ).first ) );
3750 if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3755 QTextStream stream( &file );
3756 stream <<
"GIMP Palette" << Qt::endl;
3757 if ( paletteName.isEmpty() )
3759 stream <<
"Name: QGIS Palette" << Qt::endl;
3763 stream <<
"Name: " << paletteName << Qt::endl;
3765 stream <<
"Columns: 4" << Qt::endl;
3766 stream <<
'#' << Qt::endl;
3768 for ( QgsNamedColorList::ConstIterator colorIt = colors.constBegin(); colorIt != colors.constEnd(); ++colorIt )
3770 const QColor color = ( *colorIt ).first;
3771 if ( !color.isValid() )
3775 stream << QStringLiteral(
"%1 %2 %3" ).arg( color.red(), 3 ).arg( color.green(), 3 ).arg( color.blue(), 3 );
3776 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << Qt::endl;
3787 if ( !file.open( QIODevice::ReadOnly ) )
3790 return importedColors;
3793 QTextStream in( &file );
3795 QString line = in.readLine();
3796 if ( !line.startsWith( QLatin1String(
"GIMP Palette" ) ) )
3799 return importedColors;
3803 while ( !in.atEnd() && !line.startsWith( QLatin1String(
"Name:" ) ) && !line.startsWith(
'#' ) )
3805 line = in.readLine();
3807 if ( line.startsWith( QLatin1String(
"Name:" ) ) )
3809 const thread_local QRegularExpression nameRx(
"Name:\\s*(\\S.*)$" );
3810 const QRegularExpressionMatch match = nameRx.match( line );
3811 if ( match.hasMatch() )
3813 name = match.captured( 1 );
3818 while ( !in.atEnd() && !line.startsWith(
'#' ) )
3820 line = in.readLine();
3825 return importedColors;
3829 const thread_local QRegularExpression rx(
"^\\s*(\\d+)\\s+(\\d+)\\s+(\\d+)(\\s.*)?$" );
3830 while ( !in.atEnd() )
3832 line = in.readLine();
3833 const QRegularExpressionMatch match = rx.match( line );
3834 if ( !match.hasMatch() )
3838 const int red = match.captured( 1 ).toInt();
3839 const int green = match.captured( 2 ).toInt();
3840 const int blue = match.captured( 3 ).toInt();
3841 const QColor color = QColor( red, green, blue );
3842 if ( !color.isValid() )
3849 if ( rx.captureCount() > 3 )
3851 label = match.captured( 4 ).simplified();
3858 importedColors << qMakePair( color, label );
3863 return importedColors;
3876 const thread_local QRegularExpression hexColorAlphaRx(
"^\\s*#?([0-9a-fA-F]{6})([0-9a-fA-F]{2})\\s*$" );
3877 QRegularExpressionMatch match = hexColorAlphaRx.match( colorStr );
3880 if ( !match.hasMatch() && QColor::isValidColor( colorStr ) )
3883 parsedColor.setNamedColor( colorStr );
3884 if ( parsedColor.isValid() )
3886 containsAlpha =
false;
3892 if ( match.hasMatch() )
3894 const QString hexColor = match.captured( 1 );
3895 parsedColor.setNamedColor( QStringLiteral(
"#" ) + hexColor );
3897 const int alphaHex = match.captured( 2 ).toInt( &alphaOk, 16 );
3899 if ( parsedColor.isValid() && alphaOk )
3901 parsedColor.setAlpha( alphaHex );
3902 containsAlpha =
true;
3910 const thread_local QRegularExpression hexColorRx2(
"^\\s*(?:[0-9a-fA-F]{3}){1,2}\\s*$" );
3911 if ( colorStr.indexOf( hexColorRx2 ) != -1 )
3914 parsedColor.setNamedColor( QStringLiteral(
"#" ) + colorStr );
3915 if ( parsedColor.isValid() )
3917 containsAlpha =
false;
3924 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*$" );
3925 match = rgbFormatRx.match( colorStr );
3926 if ( match.hasMatch() )
3928 const int r = match.captured( 1 ).toInt();
3929 const int g = match.captured( 2 ).toInt();
3930 const int b = match.captured( 3 ).toInt();
3931 parsedColor.setRgb( r, g, b );
3932 if ( parsedColor.isValid() )
3934 containsAlpha =
false;
3940 const thread_local QRegularExpression hslFormatRx(
"^\\s*hsl\\(?\\s*(\\d+)\\s*,\\s*(\\d+)\\s*%\\s*,\\s*(\\d+)\\s*%\\s*\\)?\\s*;?\\s*$" );
3941 match = hslFormatRx.match( colorStr );
3942 if ( match.hasMatch() )
3944 const int h = match.captured( 1 ).toInt();
3945 const int s = match.captured( 2 ).toInt();
3946 const int l = match.captured( 3 ).toInt();
3947 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0 );
3948 if ( parsedColor.isValid() )
3950 containsAlpha =
false;
3956 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*$" );
3957 match = rgbPercentFormatRx.match( colorStr );
3958 if ( match.hasMatch() )
3960 const int r = std::round( match.captured( 1 ).toDouble() * 2.55 );
3961 const int g = std::round( match.captured( 2 ).toDouble() * 2.55 );
3962 const int b = std::round( match.captured( 3 ).toDouble() * 2.55 );
3963 parsedColor.setRgb( r, g, b );
3964 if ( parsedColor.isValid() )
3966 containsAlpha =
false;
3972 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*$" );
3973 match = rgbaFormatRx.match( colorStr );
3974 if ( match.hasMatch() )
3976 const int r = match.captured( 1 ).toInt();
3977 const int g = match.captured( 2 ).toInt();
3978 const int b = match.captured( 3 ).toInt();
3979 const int a = std::round( match.captured( 4 ).toDouble() * 255.0 );
3980 parsedColor.setRgb( r, g, b, a );
3981 if ( parsedColor.isValid() )
3983 containsAlpha =
true;
3989 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*$" );
3990 match = rgbaPercentFormatRx.match( colorStr );
3991 if ( match.hasMatch() )
3993 const int r = std::round( match.captured( 1 ).toDouble() * 2.55 );
3994 const int g = std::round( match.captured( 2 ).toDouble() * 2.55 );
3995 const int b = std::round( match.captured( 3 ).toDouble() * 2.55 );
3996 const int a = std::round( match.captured( 4 ).toDouble() * 255.0 );
3997 parsedColor.setRgb( r, g, b, a );
3998 if ( parsedColor.isValid() )
4000 containsAlpha =
true;
4006 const thread_local QRegularExpression hslaPercentFormatRx(
"^\\s*hsla\\(?\\s*(\\d+)\\s*,\\s*(\\d+)\\s*%\\s*,\\s*(\\d+)\\s*%\\s*,\\s*([\\d\\.]+)\\s*\\)?\\s*;?\\s*$" );
4007 match = hslaPercentFormatRx.match( colorStr );
4008 if ( match.hasMatch() )
4010 const int h = match.captured( 1 ).toInt();
4011 const int s = match.captured( 2 ).toInt();
4012 const int l = match.captured( 3 ).toInt();
4013 const int a = std::round( match.captured( 4 ).toDouble() * 255.0 );
4014 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0, a );
4015 if ( parsedColor.isValid() )
4017 containsAlpha =
true;
4034 const QImage::Format format = image->format();
4035 if ( format != QImage::Format_ARGB32_Premultiplied && format != QImage::Format_ARGB32 )
4042 for (
int heightIndex = 0; heightIndex < image->height(); ++heightIndex )
4044 QRgb *scanLine =
reinterpret_cast< QRgb *
>( image->scanLine( heightIndex ) );
4045 for (
int widthIndex = 0; widthIndex < image->width(); ++widthIndex )
4047 myRgb = scanLine[widthIndex];
4048 if ( format == QImage::Format_ARGB32_Premultiplied )
4049 scanLine[widthIndex] = qRgba( opacity * qRed( myRgb ), opacity * qGreen( myRgb ), opacity * qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4051 scanLine[widthIndex] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4059 const int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
4060 const int alpha = ( radius < 1 ) ? 16 : ( radius > 17 ) ? 1 : tab[radius - 1];
4062 if ( image.format() != QImage::Format_ARGB32_Premultiplied
4063 && image.format() != QImage::Format_RGB32 )
4065 image = image.convertToFormat( QImage::Format_ARGB32_Premultiplied );
4068 const int r1 = rect.top();
4069 const int r2 = rect.bottom();
4070 const int c1 = rect.left();
4071 const int c2 = rect.right();
4073 const int bpl = image.bytesPerLine();
4081 i1 = i2 = ( QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3 );
4083 for (
int col = c1; col <= c2; col++ )
4085 p = image.scanLine( r1 ) + col * 4;
4086 for (
int i = i1; i <= i2; i++ )
4087 rgba[i] = p[i] << 4;
4090 for (
int j = r1; j < r2; j++, p += bpl )
4091 for (
int i = i1; i <= i2; i++ )
4092 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4095 for (
int row = r1; row <= r2; row++ )
4097 p = image.scanLine( row ) + c1 * 4;
4098 for (
int i = i1; i <= i2; i++ )
4099 rgba[i] = p[i] << 4;
4102 for (
int j = c1; j < c2; j++, p += 4 )
4103 for (
int i = i1; i <= i2; i++ )
4104 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4107 for (
int col = c1; col <= c2; col++ )
4109 p = image.scanLine( r2 ) + col * 4;
4110 for (
int i = i1; i <= i2; i++ )
4111 rgba[i] = p[i] << 4;
4114 for (
int j = r1; j < r2; j++, p -= bpl )
4115 for (
int i = i1; i <= i2; i++ )
4116 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4119 for (
int row = r1; row <= r2; row++ )
4121 p = image.scanLine( row ) + c2 * 4;
4122 for (
int i = i1; i <= i2; i++ )
4123 rgba[i] = p[i] << 4;
4126 for (
int j = c1; j < c2; j++, p -= 4 )
4127 for (
int i = i1; i <= i2; i++ )
4128 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4134 if ( alpha != 255 && alpha > 0 )
4138 const double alphaFactor = alpha / 255.;
4139 int r = 0, g = 0, b = 0;
4140 rgb.getRgb( &r, &g, &b );
4145 rgb.setRgb( r, g, b, alpha );
4147 else if ( alpha == 0 )
4149 rgb.setRgb( 0, 0, 0, 0 );
4158 if ( !simpleFill || !simpleLine )
4182 if ( simpleLine->
offset() )
4200 if ( order == Qt::AscendingOrder )
4214 const double dx = directionPoint.x() - startPoint.x();
4215 const double dy = directionPoint.y() - startPoint.y();
4216 const double length = std::sqrt( dx * dx + dy * dy );
4217 const double scaleFactor = distance / length;
4218 return QPointF( startPoint.x() + dx * scaleFactor, startPoint.y() + dy * scaleFactor );
4228 for (
int i = 0; i < svgPaths.size(); i++ )
4230 const QDir dir( svgPaths[i] );
4231 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4232 for (
const QString &item : svgSubPaths )
4234 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4237 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4238 for (
const QString &item : svgFiles )
4241 list.append( dir.path() +
'/' + item );
4253 QStringList svgPaths;
4254 svgPaths.append( directory );
4256 for (
int i = 0; i < svgPaths.size(); i++ )
4258 const QDir dir( svgPaths[i] );
4259 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4260 for (
const QString &item : svgSubPaths )
4262 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4265 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4266 for (
const QString &item : svgFiles )
4268 list.append( dir.path() +
'/' + item );
4280 if ( n.startsWith( QLatin1String(
"base64:" ) ) )
4284 if ( QFileInfo::exists( n ) )
4285 return QFileInfo( n ).canonicalFilePath();
4289 if ( name.contains( QLatin1String(
"://" ) ) )
4291 const QUrl url( name );
4292 if ( url.isValid() && !url.scheme().isEmpty() )
4294 if ( url.scheme().compare( QLatin1String(
"file" ), Qt::CaseInsensitive ) == 0 )
4297 name = url.toLocalFile();
4298 if ( QFile( name ).exists() )
4300 return QFileInfo( name ).canonicalFilePath();
4314 for (
int i = 0; i < svgPaths.size(); i++ )
4316 QString svgPath = svgPaths[i];
4317 if ( svgPath.endsWith( QChar(
'/' ) ) )
4328 const QString myLocalPath = svgPath + QDir::separator() + name;
4331 if ( QFile( myLocalPath ).exists() )
4334 return QFileInfo( myLocalPath ).canonicalFilePath();
4338 return pathResolver.
readPath( name );
4346 if ( p.startsWith( QLatin1String(
"base64:" ) ) )
4349 if ( !QFileInfo::exists( p ) )
4352 QString path = QFileInfo( p ).canonicalFilePath();
4356 bool isInSvgPaths =
false;
4357 for (
int i = 0; i < svgPaths.size(); i++ )
4359 const QString dir = QFileInfo( svgPaths[i] ).canonicalFilePath();
4361 if ( !dir.isEmpty() && path.startsWith( dir ) )
4363 path = path.mid( dir.size() + 1 );
4364 isInSvgPaths =
true;
4379 double cx = 0, cy = 0;
4380 double area, sum = 0;
4381 for (
int i = points.count() - 1, j = 0; j < points.count(); i = j++ )
4383 const QPointF &p1 = points[i];
4384 const QPointF &p2 = points[j];
4385 area = p1.x() * p2.y() - p1.y() * p2.x();
4387 cx += ( p1.x() + p2.x() ) * area;
4388 cy += ( p1.y() + p2.y() ) * area;
4395 if ( points.count() >= 2 )
4396 return QPointF( ( points[0].x() + points[1].x() ) / 2, ( points[0].y() + points[1].y() ) / 2 );
4397 else if ( points.count() == 1 )
4405 return QPointF( cx, cy );
4412 if ( ( rings && rings->count() > 0 ) || !
pointInPolygon( points, centroid ) )
4414 unsigned int i, pointCount = points.count();
4416 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( points[i].x(), points[i].y() );
4422 for (
auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
4424 pointCount = ( *ringIt ).count();
4426 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( ( *ringIt )[i].x(), ( *ringIt )[i].y() );
4432 if ( !pointOnSurfaceGeom.
isNull() )
4435 centroid.
setX( point.
x() );
4436 centroid.
setY( point.
y() );
4441 return QPointF( centroid.
x(), centroid.
y() );
4446 bool inside =
false;
4448 const double x = point.x();
4449 const double y = point.y();
4451 for (
int i = 0, j = points.count() - 1; i < points.count(); i++ )
4453 const QPointF &p1 = points[i];
4454 const QPointF &p2 = points[j];
4459 if ( ( p1.y() < y && p2.y() >= y ) || ( p2.y() < y && p1.y() >= y ) )
4461 if ( p1.x() + ( y - p1.y() ) / ( p2.y() - p1.y() ) * ( p2.x() - p1.x() ) <= x )
4472 if ( polyline.size() < 2 )
4475 double totalLength = 0;
4476 auto it = polyline.begin();
4478 for ( ; it != polyline.end(); ++it )
4480 const QPointF p2 = *it;
4481 const double segmentLength = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4482 totalLength += segmentLength;
4490 if ( polyline.size() < 2 )
4493 double totalLength = 0;
4494 auto it = polyline.begin();
4496 std::vector< double > segmentLengths( polyline.size() - 1 );
4497 auto segmentLengthIt = segmentLengths.begin();
4498 for ( ; it != polyline.end(); ++it )
4500 const QPointF p2 = *it;
4501 *segmentLengthIt = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4502 totalLength += *segmentLengthIt;
4508 if ( startOffset >= 0 && totalLength <= startOffset )
4510 if ( endOffset < 0 && totalLength <= -endOffset )
4513 const double startDistance = startOffset < 0 ? totalLength + startOffset : startOffset;
4514 const double endDistance = endOffset <= 0 ? totalLength + endOffset : endOffset;
4515 QPolygonF substringPoints;
4516 substringPoints.reserve( polyline.size() );
4518 it = polyline.begin();
4519 segmentLengthIt = segmentLengths.begin();
4522 bool foundStart =
false;
4523 if (
qgsDoubleNear( startDistance, 0.0 ) || startDistance < 0 )
4525 substringPoints << p1;
4529 double distanceTraversed = 0;
4530 for ( ; it != polyline.end(); ++it )
4532 const QPointF p2 = *it;
4533 if ( distanceTraversed < startDistance && distanceTraversed + *segmentLengthIt > startDistance )
4536 const double distanceToStart = startDistance - distanceTraversed;
4537 double startX, startY;
4539 substringPoints << QPointF( startX, startY );
4542 if ( foundStart && ( distanceTraversed + *segmentLengthIt > endDistance ) )
4545 const double distanceToEnd = endDistance - distanceTraversed;
4548 if ( substringPoints.last() != QPointF( endX, endY ) )
4549 substringPoints << QPointF( endX, endY );
4551 else if ( foundStart )
4553 if ( substringPoints.last() != QPointF( p2.x(), p2.y() ) )
4554 substringPoints << QPointF( p2.x(), p2.y() );
4557 distanceTraversed += *segmentLengthIt;
4558 if ( distanceTraversed > endDistance )
4565 if ( ( substringPoints.size() < 2 ) || ( substringPoints.size() == 2 && substringPoints.at( 0 ) == substringPoints.at( 1 ) ) )
4568 return substringPoints;
4573 double vertexAngle = M_PI - ( std::atan2( p3.y() - p2.y(), p3.x() - p2.x() ) - std::atan2( p2.y() - p1.y(), p2.x() - p1.x() ) );
4577 return vertexAngle < M_PI * 135.0 / 180.0 || vertexAngle > M_PI * 225.0 / 180.0;
4582 target.reserve( target.size() + line.size() );
4583 for (
const QPointF &pt : line )
4585 if ( !target.empty() && target.last() == pt )
4594 if ( fieldOrExpression.isEmpty() )
4629 QList<double> breaks;
4632 breaks.append( maximum );
4636 const int minimumCount =
static_cast< int >( classes ) / 3;
4637 const double shrink = 0.75;
4638 const double highBias = 1.5;
4639 const double adjustBias = 0.5 + 1.5 * highBias;
4640 const int divisions = classes;
4641 const double h = highBias;
4644 const double dx = maximum - minimum;
4654 cell = std::max( std::fabs( minimum ), std::fabs( maximum ) );
4655 if ( adjustBias >= 1.5 * h + 0.5 )
4657 U = 1 + ( 1.0 / ( 1 + h ) );
4661 U = 1 + ( 1.5 / ( 1 + adjustBias ) );
4663 small = dx < ( cell * U * std::max( 1, divisions ) * 1e-07 * 3.0 );
4670 cell = 9 + cell / 10;
4671 cell = cell * shrink;
4673 if ( minimumCount > 1 )
4675 cell = cell / minimumCount;
4681 if ( divisions > 1 )
4683 cell = cell / divisions;
4686 if ( cell < 20 * 1e-07 )
4691 const double base = std::pow( 10.0, std::floor( std::log10( cell ) ) );
4693 if ( ( 2 * base ) - cell < h * ( cell - unit ) )
4696 if ( ( 5 * base ) - cell < adjustBias * ( cell - unit ) )
4699 if ( ( 10.0 * base ) - cell < h * ( cell - unit ) )
4706 int start = std::floor( minimum / unit + 1e-07 );
4707 int end = std::ceil( maximum / unit - 1e-07 );
4710 while ( start * unit > minimum + ( 1e-07 * unit ) )
4714 while ( end * unit < maximum - ( 1e-07 * unit ) )
4722 int k = std::floor( 0.5 + end - start );
4723 if ( k < minimumCount )
4725 k = minimumCount - k;
4729 start = start - k / 2 + k % 2;
4733 start = start - k / 2;
4734 end = end + k / 2 + k % 2;
4737 const double minimumBreak = start * unit;
4739 const int count = end - start;
4741 breaks.reserve( count );
4742 for (
int i = 1; i < count + 1; i++ )
4744 breaks.append( minimumBreak + i * unit );
4747 if ( breaks.isEmpty() )
4750 if ( breaks.first() < minimum )
4752 breaks[0] = minimum;
4754 if ( breaks.last() > maximum )
4756 breaks[breaks.count() - 1] = maximum;
4761 if ( minimum < 0.0 && maximum > 0.0 )
4763 QList<double> breaksMinusZero;
4764 for (
int i = 0; i < breaks.count(); i++ )
4766 breaksMinusZero.append( breaks[i] - 0.0 );
4769 for (
int i = 1; i < breaks.count(); i++ )
4771 if ( std::abs( breaksMinusZero[i] ) < std::abs( breaksMinusZero[i - 1] ) )
4774 breaks[posOfMin] = 0.0;
4783 bool roundToUnit =
false;
4786 if ( props.contains( QStringLiteral(
"uomScale" ) ) )
4789 scale = props.value( QStringLiteral(
"uomScale" ) ).toDouble( &ok );
4798 if ( props.value( QStringLiteral(
"uom" ) ) == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
4823 scale = 1 / 0.28 * 25.4;
4847 double rescaled = size * scale;
4852 rescaled = std::round( rescaled );
4859 const double x =
rescaleUom( point.x(), unit, props );
4860 const double y =
rescaleUom( point.y(), unit, props );
4861 return QPointF( x, y );
4866 QVector<qreal> result;
4867 QVector<qreal>::const_iterator it = array.constBegin();
4868 for ( ; it != array.constEnd(); ++it )
4870 result.append(
rescaleUom( *it, unit, props ) );
4877 if ( !props.value( QStringLiteral(
"scaleMinDenom" ), QString() ).toString().isEmpty() )
4879 QDomElement scaleMinDenomElem = doc.createElement( QStringLiteral(
"se:MinScaleDenominator" ) );
4880 scaleMinDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMinDenom" ) ).toString().toDouble() ) ) );
4881 ruleElem.appendChild( scaleMinDenomElem );
4884 if ( !props.value( QStringLiteral(
"scaleMaxDenom" ), QString() ).toString().isEmpty() )
4886 QDomElement scaleMaxDenomElem = doc.createElement( QStringLiteral(
"se:MaxScaleDenominator" ) );
4887 scaleMaxDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMaxDenom" ) ).toString().toDouble() ) ) );
4888 ruleElem.appendChild( scaleMaxDenomElem );
4897 const double parentScaleMinDenom = props.value( QStringLiteral(
"scaleMinDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
4898 if ( !ok || parentScaleMinDenom <= 0 )
4899 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( mScaleMinDenom );
4901 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( std::max( parentScaleMinDenom, mScaleMinDenom ) );
4907 const double parentScaleMaxDenom = props.value( QStringLiteral(
"scaleMaxDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
4908 if ( !ok || parentScaleMaxDenom <= 0 )
4909 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( mScaleMaxDenom );
4911 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( std::min( parentScaleMaxDenom, mScaleMaxDenom ) );
4919 if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
4921 scale = 1.0 / 0.00028;
4923 else if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
4925 scale = 304.8 / 0.28;
4932 return size * scale;
4940 SymbolLayerVisitor(
const QSet<QgsSymbolLayerId> &layerIds )
4941 : mSymbolLayerIds( layerIds )
4954 void visitSymbol(
const QgsSymbol *symbol,
const QString &identifier, QVector<int> rootPath )
4958 QVector<int> indexPath = rootPath;
4959 indexPath.append( idx );
4961 if ( mSymbolLayerIds.contains(
QgsSymbolLayerId( mCurrentRuleKey + identifier, indexPath ) ) )
4963 mSymbolLayers.insert( sl );
4968 visitSymbol( subSymbol, identifier, indexPath );
4977 if ( symbolEntity->symbol() )
4979 visitSymbol( symbolEntity->symbol(), leaf.
identifier, {} );
4985 QString mCurrentRuleKey;
4986 const QSet<QgsSymbolLayerId> &mSymbolLayerIds;
4987 QSet<const QgsSymbolLayer *> mSymbolLayers;
4990 SymbolLayerVisitor visitor( symbolLayerIds );
4991 renderer->
accept( &visitor );
4992 return visitor.mSymbolLayers;
5000 SymbolRefreshRateVisitor()
5012 void visitSymbol(
const QgsSymbol *symbol )
5029 if ( refreshRate == -1 || ( animatedMarker->frameRate() > refreshRate ) )
5030 refreshRate = animatedMarker->frameRate();
5034 visitSymbol( subSymbol );
5042 if (
QgsSymbol *symbol = qgis::down_cast<const QgsStyleSymbolEntity *>( leaf.
entity )->symbol() )
5044 visitSymbol( symbol );
5050 double refreshRate = -1;
5053 SymbolRefreshRateVisitor visitor;
5054 renderer->
accept( &visitor );
5055 return visitor.refreshRate;
5060 if ( !s || !context )
5086 size = markerSymbol->
size( *context );
5088 else if ( lineSymbol )
5090 size = lineSymbol->
width( *context );
5102 if ( minSize > 0 && size < minSize )
5106 else if ( maxSize > 0 && size > maxSize )
5125 else if ( lineSymbol )
5140 QMap<QString, QgsProperty>::const_iterator paramIt = propertiesMap.constBegin();
5141 for ( ; paramIt != propertiesMap.constEnd(); ++paramIt )
5143 properties.insert( paramIt.key(), paramIt.value().valueAsString( context ) );
5151 angleRad = std::fmod( angleRad, M_PI * 2 );
5155 angleRad += M_PI * 2;
5159 struct rationalTangent
5171 static const QList<rationalTangent> __rationalTangents
5173 { 1, 57, 0.01754206006 },
5174 { 3, 86, 0.03486958155 },
5175 { 1, 19, 0.05258306161 },
5176 { 3, 43, 0.06965457373 },
5177 { 7, 80, 0.08727771295 },
5178 { 2, 19, 0.1048769387 },
5179 { 7, 57, 0.1221951707 },
5180 { 9, 64, 0.1397088743 },
5181 { 13, 82, 0.157228051 },
5182 { 3, 17, 0.174672199 },
5183 { 7, 36, 0.1920480172 },
5184 { 17, 80, 0.209385393 },
5185 { 3, 13, 0.2267988481 },
5186 { 1, 4, 0.2449786631 },
5187 { 26, 97, 0.2618852647 },
5188 { 27, 94, 0.2797041525 },
5189 { 26, 85, 0.2968446734 },
5190 { 13, 40, 0.3142318991 },
5191 { 21, 61, 0.3315541619 },
5192 { 4, 11, 0.3487710036 },
5193 { 38, 99, 0.3664967859 },
5194 { 40, 99, 0.383984624 },
5195 { 31, 73, 0.4015805401 },
5196 { 41, 92, 0.4192323938 },
5197 { 7, 15, 0.4366271598 },
5198 { 20, 41, 0.4538440015 },
5199 { 27, 53, 0.4711662643 },
5200 { 42, 79, 0.4886424026 },
5201 { 51, 92, 0.5061751436 },
5202 { 56, 97, 0.5235757641 },
5203 { 3, 5, 0.5404195003 },
5204 { 5, 8, 0.5585993153 },
5205 { 50, 77, 0.5759185996 },
5206 { 29, 43, 0.5933501462 },
5207 { 7, 10, 0.6107259644 },
5208 { 69, 95, 0.6281701124 },
5209 { 52, 69, 0.6458159195 },
5210 { 25, 32, 0.6632029927 },
5211 { 17, 21, 0.6805212247 },
5212 { 73, 87, 0.6981204504 },
5213 { 73, 84, 0.7154487784 },
5214 { 9, 10, 0.7328151018 },
5215 { 83, 89, 0.7505285818 },
5216 { 28, 29, 0.7678561033 },
5217 { 1, 1, 0.7853981634 },
5218 { 29, 28, 0.8029402235 },
5219 { 89, 83, 0.820267745 },
5220 { 10, 9, 0.837981225 },
5221 { 107, 93, 0.855284165 },
5222 { 87, 73, 0.8726758763 },
5223 { 121, 98, 0.8900374031 },
5224 { 32, 25, 0.9075933341 },
5225 { 69, 52, 0.9249804073 },
5226 { 128, 93, 0.9424647244 },
5227 { 10, 7, 0.9600703624 },
5228 { 43, 29, 0.9774461806 },
5229 { 77, 50, 0.9948777272 },
5230 { 8, 5, 1.012197011 },
5231 { 163, 98, 1.029475114 },
5232 { 168, 97, 1.047174539 },
5233 { 175, 97, 1.064668696 },
5234 { 126, 67, 1.082075603 },
5235 { 157, 80, 1.099534652 },
5236 { 203, 99, 1.117049384 },
5237 { 193, 90, 1.134452855 },
5238 { 146, 65, 1.151936673 },
5239 { 139, 59, 1.169382787 },
5240 { 99, 40, 1.186811703 },
5241 { 211, 81, 1.204257817 },
5242 { 272, 99, 1.221730164 },
5243 { 273, 94, 1.239188479 },
5244 { 277, 90, 1.25664606 },
5245 { 157, 48, 1.274088705 },
5246 { 279, 80, 1.291550147 },
5247 { 362, 97, 1.308990773 },
5248 { 373, 93, 1.326448578 },
5249 { 420, 97, 1.343823596 },
5250 { 207, 44, 1.361353157 },
5251 { 427, 83, 1.378810994 },
5252 { 414, 73, 1.396261926 },
5253 { 322, 51, 1.413716057 },
5254 { 185, 26, 1.431170275 },
5255 { 790, 97, 1.448623034 },
5256 { 333, 35, 1.466075711 },
5257 { 1063, 93, 1.483530284 },
5258 { 1330, 93, 1.500985147 },
5259 { 706, 37, 1.518436297 },
5260 { 315, 11, 1.535889876 },
5261 { 3953, 69, 1.553343002 },
5267 static const QList<rationalTangent> rationalTangents
5269 { 1, 10, qDegreesToRadians( 5.71059 ) },
5270 { 1, 5, qDegreesToRadians( 11.3099 ) },
5271 { 1, 4, qDegreesToRadians( 14.0362 ) },
5272 { 1, 4, qDegreesToRadians( 18.4349 ) },
5273 { 1, 2, qDegreesToRadians( 26.5651 ) },
5274 { 2, 3, qDegreesToRadians( 33.6901 ) },
5275 { 1, 1, qDegreesToRadians( 45.0 ) },
5276 { 3, 2, qDegreesToRadians( 56.3099 ) },
5277 { 2, 1, qDegreesToRadians( 63.4349 ) },
5278 { 3, 1, qDegreesToRadians( 71.5651 ) },
5279 { 4, 1, qDegreesToRadians( 75.9638 ) },
5280 { 10, 1, qDegreesToRadians( 84.2894 ) },
5283 const int quadrant {
static_cast<int>( angleRad / M_PI_2 ) };
5284 Q_ASSERT( quadrant >= 0 && quadrant <= 3 );
5296 angleRad -= M_PI / 2;
5306 angleRad -= M_PI + M_PI_2;
5328 for (
int idx = 0; idx < rationalTangents.count(); ++idx )
5330 const auto item = rationalTangents.at( idx );
5331 if (
qgsDoubleNear( item.angle, angleRad, 10E-3 ) || item.angle > angleRad )
5338 const rationalTangent bTan { rationalTangents.at( rTanIdx ) };
5339 angleRad = bTan.angle;
5340 const double k { bTan.q *height *width / std::cos( angleRad ) };
5341 const int hcfH { std::gcd( bTan.p * height, bTan.q * width ) };
5342 const int hcfW { std::gcd( bTan.q * height, bTan.p * width ) };
5343 const int W1 {
static_cast<int>( std::round( k / hcfW ) ) };
5344 const int H1 {
static_cast<int>( std::round( k / hcfH ) ) };
5357 angleRad += M_PI / 2;
5370 angleRad += M_PI + M_PI_2;
5381template <
typename Functor>
5384 sl->
setId( generateId() );
5392template <
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 QColor colorFromString(const QString &string)
Decodes a string into a color value.
static QString colorToString(const QColor &color)
Encodes a color into a string value.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates the symbol layer.
static QString typeString()
Returns the string identifier for QgsCptCityColorRamp.
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 void pointOnLineWithDistance(double x1, double y1, double x2, double y2, double distance, double &x, double &y, double *z1=nullptr, double *z2=nullptr, double *z=nullptr, double *m1=nullptr, double *m2=nullptr, double *m=nullptr)
Calculates the point a specified distance from (x1, y1) toward a second point (x2,...
static double normalizedAngle(double angle)
Ensures that an angle is in the range 0 <= angle < 2 pi.
A geometry is the spatial representation of a feature.
QgsMultiPolygonXY asMultiPolygon() const
Returns the contents of the geometry as a multi-polygon.
QgsGeometry offsetCurve(double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit) const
Returns an offset line at a given distance and side from an input line.
QgsGeometry pointOnSurface() const
Returns a point guaranteed to lie on the surface of a geometry.
static QgsGeometry fromPolylineXY(const QgsPolylineXY &polyline)
Creates a new LineString geometry from a list of QgsPointXY points.
QgsPolygonXY asPolygon() const
Returns the contents of the geometry as a polygon.
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.
QSet< int > propertyKeys() const final
Returns a list of property keys contained within the collection.
QgsProperty property(int key) const final
Returns a matching property from the collection, if one exists.
A store for object properties.
bool isProjectColor() const
Returns true if the property is set to a linked project color.
bool isActive() const
Returns whether the property is currently active.
void setActive(bool active)
Sets whether the property is currently active.
The class is used as a container of context for various read/write operations on other objects.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
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)
virtual QgsSymbolLayer * clone() const =0
Shall be reimplemented by subclasses to create a deep copy of the instance.
virtual bool setSubSymbol(QgsSymbol *symbol)
Sets layer's subsymbol. takes ownership of the passed symbol.
void setId(const QString &id)
Set symbol layer identifier This id has to be unique in the whole project.
bool isLocked() const
Returns true if the symbol layer colors are locked and the layer will ignore any symbol-level color c...
Property
Data definable properties.
void setPaintEffect(QgsPaintEffect *effect)
Sets the current paint effect for the layer.
void setRenderingPass(int renderingPass)
Specifies the rendering pass in which this symbol layer should be rendered.
virtual double estimateMaxBleed(const QgsRenderContext &context) const
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the layer.
void setEnabled(bool enabled)
Sets whether symbol layer is enabled and should be drawn.
virtual QVariantMap properties() const =0
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
void setUserFlags(Qgis::SymbolLayerUserFlags flags)
Sets user-controlled flags which control the symbol layer's behavior.
bool enabled() const
Returns true if symbol layer is enabled and will be drawn.
virtual QString layerType() const =0
Returns a string that represents this layer type.
int renderingPass() const
Specifies the rendering pass in which this symbol layer should be rendered.
QString id() const
Returns symbol layer identifier This id is unique in the whole project.
virtual void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the layer.
virtual QgsSymbol * subSymbol()
Returns the symbol's sub symbol, if present.
Qgis::SymbolLayerUserFlags userFlags() const
Returns user-controlled flags which control the symbol layer's behavior.
virtual QColor color() const
Returns the "representative" color of the symbol layer.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol layer property definitions.
void setLocked(bool locked)
Sets whether the layer's colors are locked.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
virtual bool hasDataDefinedProperties() const
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
void setOriginalGeometryType(Qgis::GeometryType type)
Sets the geometry type for the original feature geometry being rendered.
Abstract base class for all rendered symbols.
void setOutputUnit(Qgis::RenderUnit unit) const
Sets the units to use for sizes and widths within the symbol.
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol's property collection, used for data defined overrides.
QgsSymbolAnimationSettings & animationSettings()
Returns a reference to the symbol animation settings.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol property definitions.
Qgis::SymbolFlags flags() const
Returns flags for the symbol.
qreal opacity() const
Returns the opacity for the symbol.
void setMapUnitScale(const QgsMapUnitScale &scale) const
Sets the map unit scale for the symbol.
bool clipFeaturesToExtent() const
Returns whether features drawn by the symbol will be clipped to the render context's extent.
void setFlags(Qgis::SymbolFlags flags)
Sets flags for the symbol.
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, bool silenceNullWarnings=false)
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.