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 )
719 case Qgis::RenderUnit::MapUnits:
721 *scaleFactor = 0.001;
722 return QStringLiteral(
"http://www.opengeospatial.org/se/units/metre" );
724 case Qgis::RenderUnit::MetersInMapUnits:
727 return QStringLiteral(
"http://www.opengeospatial.org/se/units/metre" );
729 case Qgis::RenderUnit::Millimeters:
734 *scaleFactor = 1 / 0.28;
743 if (
str == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
747 return Qgis::RenderUnit::MetersInMapUnits;
749 else if (
str == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
752 *scaleFactor = 0.3048;
753 return Qgis::RenderUnit::MetersInMapUnits;
761 return Qgis::RenderUnit::Pixels;
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 ) );
880 QPixmap pixmap( size );
881 pixmap.fill( Qt::transparent );
883 painter.begin( &pixmap );
888 painter.setRenderHint( QPainter::Antialiasing );
889 painter.setRenderHint( QPainter::SmoothPixmapTransform );
899 size.setWidth( size.rwidth() - ( padding * 2 ) );
900 size.setHeight( size.rheight() - ( padding * 2 ) );
901 painter.translate( padding, padding );
911 std::unique_ptr<QgsSymbol> symbol_noDD( symbol->
clone( ) );
913 for (
const auto &layer : layers )
915 for (
int i = 0; i < layer->dataDefinedProperties().count(); ++i )
917 QgsProperty &prop = layer->dataDefinedProperties().property( i );
923 symbol_noDD->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape );
927 std::unique_ptr<QgsSymbol> symbolClone( symbol->
clone( ) );
928 symbolClone->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape );
942 maxBleed = layerMaxBleed > maxBleed ? layerMaxBleed : maxBleed;
952 painter.begin( &picture );
953 painter.setRenderHint( QPainter::Antialiasing );
961 QgsSymbolRenderContext symbolContext( renderContext, units, 1.0,
false, Qgis::SymbolRenderHints(),
nullptr );
963 switch ( parentSymbolType )
978 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
979 layerClone->drawPreviewIcon( symbolContext, size );
986 QPixmap pixmap( size );
987 pixmap.fill( Qt::transparent );
989 painter.begin( &pixmap );
990 painter.setRenderHint( QPainter::Antialiasing );
1001 switch ( parentSymbolType )
1016 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
1017 layerClone->drawPreviewIcon( symbolContext, size );
1019 return QIcon( pixmap );
1029 QPixmap pixmap( size );
1030 pixmap.fill( Qt::transparent );
1033 painter.begin( &pixmap );
1036 if ( drawTransparentBackground )
1037 drawStippledBackground( &painter, QRect( padding, padding, size.width() - padding * 2, size.height() - padding * 2 ) );
1041 switch ( direction )
1043 case Qt::Horizontal:
1045 for (
int i = 0; i < size.width(); i++ )
1047 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.width() ) );
1048 painter.setPen( pen );
1049 const int x = flipDirection ? size.width() - i - 1 : i;
1050 painter.drawLine( x, 0 + padding, x, size.height() - 1 - padding );
1057 for (
int i = 0; i < size.height(); i++ )
1059 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.height() ) );
1060 painter.setPen( pen );
1061 const int y = flipDirection ? size.height() - i - 1 : i;
1062 painter.drawLine( 0 + padding, y, size.width() - 1 - padding, y );
1075 uchar pixDataRGB[] = { 255, 255, 255, 255,
1080 const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
1082 const int width = ( rect.width() < rect.height() ) ?
1083 rect.width() / 2.5 : rect.height() / 2.5;
1084 const QPixmap pix = QPixmap::fromImage( img.scaled( width, width ) );
1087 brush.setTexture( pix );
1088 painter->fillRect( rect, brush );
1093 const qreal s = ( markerSize - 1 ) / 2.0;
1098 p.setPen( QColor( 50, 100, 120, 200 ) );
1099 p.setBrush( QColor( 200, 200, 210, 120 ) );
1100 p.drawEllipse( x - s, y - s, s * 2, s * 2 );
1103 p.setPen( QColor( 255, 0, 0 ) );
1104 p.drawLine( x - s, y + s, x + s, y - s );
1105 p.drawLine( x - s, y - s, x + s, y + s );
1117static QPolygonF makeOffsetGeometry(
const QgsPolylineXY &polyline )
1119 int i, pointCount = polyline.count();
1121 QPolygonF resultLine;
1122 resultLine.resize( pointCount );
1126 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1127 resultLine[i] = QPointF( tempPtr->
x(), tempPtr->
y() );
1131static QList<QPolygonF> makeOffsetGeometry(
const QgsPolygonXY &polygon )
1133 QList<QPolygonF> resultGeom;
1134 resultGeom.reserve( polygon.size() );
1135 for (
int ring = 0; ring < polygon.size(); ++ring )
1136 resultGeom.append( makeOffsetGeometry( polygon[ ring ] ) );
1142 QList<QPolygonF> resultLine;
1144 if ( polyline.count() < 2 )
1146 resultLine.append( polyline );
1150 unsigned int i, pointCount = polyline.count();
1153 QPointF *tempPtr = polyline.data();
1154 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1155 tempPolyline[i] =
QgsPointXY( tempPtr->rx(), tempPtr->ry() );
1158 if ( !tempGeometry.
isNull() )
1160 const int quadSegments = 0;
1161 const double miterLimit = 2.0;
1163 if ( geometryType == Qgis::GeometryType::Polygon )
1164 offsetGeom = tempGeometry.
buffer( -dist, quadSegments, Qgis::EndCapStyle::Flat,
1165 Qgis::JoinStyle::Miter, miterLimit );
1167 offsetGeom = tempGeometry.
offsetCurve( dist, quadSegments, Qgis::JoinStyle::Miter, miterLimit );
1169 if ( !offsetGeom.
isNull() )
1171 tempGeometry = offsetGeom;
1176 resultLine.append( makeOffsetGeometry( line ) );
1181 resultLine.append( makeOffsetGeometry( tempGeometry.
asPolygon() ) );
1187 resultLine.reserve( tempMPolyline.count() );
1188 for (
int part = 0; part < tempMPolyline.count(); ++part )
1190 resultLine.append( makeOffsetGeometry( tempMPolyline[ part ] ) );
1197 resultLine.reserve( tempMPolygon.count() );
1198 for (
int part = 0; part < tempMPolygon.count(); ++part )
1200 resultLine.append( makeOffsetGeometry( tempMPolygon[ part ] ) );
1208 resultLine.append( polyline );
1218 QDomNode layerNode = element.firstChild();
1220 while ( !layerNode.isNull() )
1222 QDomElement e = layerNode.toElement();
1223 if ( !e.isNull() && e.tagName() != QLatin1String(
"data_defined_properties" ) )
1225 if ( e.tagName() != QLatin1String(
"layer" ) )
1234 const QDomElement s = e.firstChildElement( QStringLiteral(
"symbol" ) );
1237 std::unique_ptr< QgsSymbol > subSymbol(
loadSymbol( s, context ) );
1244 layers.append( layer );
1246 for (
int i = 0; i < subSymbol->symbolLayerCount(); ++i )
1248 layers.append( subSymbol->symbolLayer( i )->clone() );
1253 const bool res = layer->setSubSymbol( subSymbol.release() );
1256 QgsDebugMsg( QStringLiteral(
"symbol layer refused subsymbol: " ) + s.attribute(
"name" ) );
1258 layers.append( layer );
1263 layers.append( layer );
1268 layerNode = layerNode.nextSibling();
1271 if ( layers.isEmpty() )
1273 QgsDebugMsg( QStringLiteral(
"no layers for symbol" ) );
1277 const QString symbolType = element.attribute( QStringLiteral(
"type" ) );
1280 if ( symbolType == QLatin1String(
"line" ) )
1282 else if ( symbolType == QLatin1String(
"fill" ) )
1284 else if ( symbolType == QLatin1String(
"marker" ) )
1288 QgsDebugMsg(
"unknown symbol type " + symbolType );
1292 if ( element.hasAttribute( QStringLiteral(
"outputUnit" ) ) )
1296 if ( element.hasAttribute( ( QStringLiteral(
"mapUnitScale" ) ) ) )
1299 const double oldMin = element.attribute( QStringLiteral(
"mapUnitMinScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1300 mapUnitScale.
minScale = oldMin != 0 ? 1.0 / oldMin : 0;
1301 const double oldMax = element.attribute( QStringLiteral(
"mapUnitMaxScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1302 mapUnitScale.
maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
1305 symbol->
setOpacity( element.attribute( QStringLiteral(
"alpha" ), QStringLiteral(
"1.0" ) ).toDouble() );
1306 symbol->
setClipFeaturesToExtent( element.attribute( QStringLiteral(
"clip_to_extent" ), QStringLiteral(
"1" ) ).toInt() );
1307 symbol->
setForceRHR( element.attribute( QStringLiteral(
"force_rhr" ), QStringLiteral(
"0" ) ).toInt() );
1308 Qgis::SymbolFlags flags;
1309 if ( element.attribute( QStringLiteral(
"renderer_should_use_levels" ), QStringLiteral(
"0" ) ).toInt() )
1316 const QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1317 if ( !ddProps.isNull() )
1327 const QString layerClass = element.attribute( QStringLiteral(
"class" ) );
1328 const bool locked = element.attribute( QStringLiteral(
"locked" ) ).toInt();
1329 const bool enabled = element.attribute( QStringLiteral(
"enabled" ), QStringLiteral(
"1" ) ).toInt();
1330 const int pass = element.attribute( QStringLiteral(
"pass" ) ).toInt();
1331 const QString
id = element.attribute( QStringLiteral(
"id" ) );
1350 if ( !
id.isEmpty() )
1354 const QDomElement effectElem = element.firstChildElement( QStringLiteral(
"effect" ) );
1355 if ( !effectElem.isNull() )
1363 const QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1364 if ( !ddProps.isNull() )
1371 const QSet< int > oldKeys = prevProperties.
propertyKeys();
1372 for (
int key : oldKeys )
1393 return QStringLiteral(
"line" );
1395 return QStringLiteral(
"marker" );
1397 return QStringLiteral(
"fill" );
1406 QDomElement symEl = doc.createElement( QStringLiteral(
"symbol" ) );
1407 symEl.setAttribute( QStringLiteral(
"type" ), _nameForSymbolType( symbol->
type() ) );
1408 symEl.setAttribute( QStringLiteral(
"name" ), name );
1409 symEl.setAttribute( QStringLiteral(
"alpha" ), QString::number( symbol->
opacity() ) );
1410 symEl.setAttribute( QStringLiteral(
"clip_to_extent" ), symbol->
clipFeaturesToExtent() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1411 symEl.setAttribute( QStringLiteral(
"force_rhr" ), symbol->
forceRHR() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1413 symEl.setAttribute( QStringLiteral(
"renderer_should_use_levels" ), QStringLiteral(
"1" ) );
1415 symEl.setAttribute( QStringLiteral(
"is_animated" ), symbol->
animationSettings().
isAnimated() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1420 QDomElement ddProps = doc.createElement( QStringLiteral(
"data_defined_properties" ) );
1422 symEl.appendChild( ddProps );
1428 QDomElement layerEl = doc.createElement( QStringLiteral(
"layer" ) );
1429 layerEl.setAttribute( QStringLiteral(
"class" ), layer->
layerType() );
1430 layerEl.setAttribute( QStringLiteral(
"enabled" ), layer->
enabled() );
1431 layerEl.setAttribute( QStringLiteral(
"locked" ), layer->
isLocked() );
1432 layerEl.setAttribute( QStringLiteral(
"pass" ), layer->
renderingPass() );
1433 layerEl.setAttribute( QStringLiteral(
"id" ), layer->
id() );
1445 QDomElement ddProps = doc.createElement( QStringLiteral(
"data_defined_properties" ) );
1447 layerEl.appendChild( ddProps );
1451 const QString subname = QStringLiteral(
"@%1@%2" ).arg( name ).arg( i );
1452 const QDomElement subEl =
saveSymbol( subname, subSymbol, doc, context );
1453 layerEl.appendChild( subEl );
1455 symEl.appendChild( layerEl );
1463 QDomDocument doc( QStringLiteral(
"qgis-symbol-definition" ) );
1466 QTextStream stream( &props );
1467 symbolElem.save( stream, -1 );
1473 QList<QgsSymbolLayer *> &layers )
1477 if ( element.isNull() )
1482 const QString symbolizerName = element.localName();
1484 if ( symbolizerName == QLatin1String(
"PointSymbolizer" ) )
1487 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1488 if ( graphicElem.isNull() )
1490 QgsDebugMsg( QStringLiteral(
"Graphic element not found in PointSymbolizer" ) );
1496 case Qgis::GeometryType::Polygon:
1504 case Qgis::GeometryType::Point:
1512 case Qgis::GeometryType::Line:
1526 if ( symbolizerName == QLatin1String(
"LineSymbolizer" ) )
1529 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1530 if ( strokeElem.isNull() )
1532 QgsDebugMsg( QStringLiteral(
"Stroke element not found in LineSymbolizer" ) );
1538 case Qgis::GeometryType::Polygon:
1539 case Qgis::GeometryType::Line:
1548 case Qgis::GeometryType::Point:
1562 if ( symbolizerName == QLatin1String(
"PolygonSymbolizer" ) )
1565 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1566 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1567 if ( fillElem.isNull() && strokeElem.isNull() )
1569 QgsDebugMsg( QStringLiteral(
"neither Fill nor Stroke element not found in PolygonSymbolizer" ) );
1577 case Qgis::GeometryType::Polygon:
1587 if ( l->
layerType() == QLatin1String(
"SimpleFill" ) || l->
layerType() == QLatin1String(
"SVGFill" ) )
1599 case Qgis::GeometryType::Line:
1607 case Qgis::GeometryType::Point:
1623 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1624 if ( fillElem.isNull() )
1626 QgsDebugMsg( QStringLiteral(
"Fill element not found" ) );
1648 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1649 if ( strokeElem.isNull() )
1651 QgsDebugMsg( QStringLiteral(
"Stroke element not found" ) );
1667 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1668 if ( graphicElem.isNull() )
1670 QgsDebugMsg( QStringLiteral(
"Graphic element not found" ) );
1695 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1696 if ( graphicElem.isNull() )
1699 const QDomElement externalGraphicElem = graphicElem.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
1700 if ( externalGraphicElem.isNull() )
1704 const QDomElement formatElem = externalGraphicElem.firstChildElement( QStringLiteral(
"Format" ) );
1705 if ( formatElem.isNull() )
1708 const QString elementFormat = formatElem.firstChild().nodeValue();
1709 if ( ! format.isEmpty() && elementFormat != format )
1711 QgsDebugMsgLevel(
"unsupported External Graphic format found: " + elementFormat, 4 );
1716 const QDomElement onlineResourceElem = externalGraphicElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1717 const QDomElement inlineContentElem = externalGraphicElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1718 if ( !onlineResourceElem.isNull() )
1723 else if ( !inlineContentElem.isNull() )
1736 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1737 if ( graphicElem.isNull() )
1740 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1741 if ( markElem.isNull() )
1744 const QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
1745 return !wellKnownNameElem.isNull();
1751 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1752 if ( graphicElem.isNull() )
1755 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1756 if ( markElem.isNull() )
1760 const QDomElement formatElem = markElem.firstChildElement( QStringLiteral(
"Format" ) );
1761 if ( formatElem.isNull() )
1764 const QString format = formatElem.firstChild().nodeValue();
1765 if ( format != QLatin1String(
"ttf" ) )
1767 QgsDebugMsg(
"unsupported Graphic Mark format found: " + format );
1772 const QDomElement onlineResourceElem = markElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1773 const QDomElement inlineContentElem = markElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1774 if ( !onlineResourceElem.isNull() )
1777 const QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
1778 if ( !markIndexElem.isNull() )
1781 else if ( !inlineContentElem.isNull() )
1796 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1797 if ( graphicElem.isNull() )
1801 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
1803 if ( it.key() == QLatin1String(
"widthHeightFactor" ) )
1814 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1815 if ( strokeElem.isNull() )
1818 QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral(
"GraphicStroke" ) );
1819 if ( graphicStrokeElem.isNull() )
1827 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1828 if ( fillElem.isNull() )
1831 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1832 if ( graphicFillElem.isNull() )
1835 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1836 if ( graphicElem.isNull() )
1842 QColor fillColor, strokeColor;
1843 double size, strokeWidth;
1844 Qt::PenStyle strokeStyle;
1845 if ( !
wellKnownMarkerFromSld( graphicElem, name, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
1848 if ( name != QLatin1String(
"horline" ) )
1856 const double angle = angleFunc.toDouble( &ok );
1862 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1863 if ( fillElem.isNull() )
1866 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1867 if ( graphicFillElem.isNull() )
1870 const QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1871 if ( graphicElem.isNull() )
1874 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1875 if ( markElem.isNull() )
1883 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1884 if ( fillElem.isNull() )
1887 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1888 if ( graphicFillElem.isNull() )
1896 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1897 if ( fillElem.isNull() )
1900 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1901 if ( graphicFillElem.isNull() )
1921 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1922 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1926 bool validFill =
false, validStroke =
false;
1931 Qt::BrushStyle fillStyle;
1933 if (
fillFromSld( fillElem, fillStyle, fillColor ) )
1939 Qt::PenStyle strokeStyle;
1940 double strokeWidth = 1.0, dashOffset = 0.0;
1941 QVector<qreal> customDashPattern;
1943 if (
lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth,
1944 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
1947 if ( validFill || validStroke )
1950 map[QStringLiteral(
"name" )] = QStringLiteral(
"square" );
1951 map[QStringLiteral(
"color" )] =
encodeColor( validFill ? fillColor : Qt::transparent );
1952 map[QStringLiteral(
"color_border" )] =
encodeColor( validStroke ? strokeColor : Qt::transparent );
1953 map[QStringLiteral(
"size" )] = QString::number( 6 );
1954 map[QStringLiteral(
"angle" )] = QString::number( 0 );
1955 map[QStringLiteral(
"offset" )] =
encodePoint( QPointF( 0, 0 ) );
1962 bool validFill =
false, validStroke =
false;
1965 QString name, format;
1967 QColor fillColor, strokeColor;
1968 double strokeWidth = 1.0, size = 0.0,
angle = 0.0;
1972 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1973 if ( !graphicFillElem.isNull() )
1976 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1977 if ( !graphicElem.isNull() )
1983 const QDomElement graphicChildElem = graphicElem.firstChildElement();
1984 while ( !graphicChildElem.isNull() )
1986 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
1989 const QDomElement wellKnownNameElem = graphicChildElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
1990 if ( !wellKnownNameElem.isNull() )
1992 name = wellKnownNameElem.firstChild().nodeValue();
1998 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) || graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2001 const QDomElement formatElem = graphicChildElem.firstChildElement( QStringLiteral(
"Format" ) );
2002 if ( formatElem.isNull() )
2005 format = formatElem.firstChild().nodeValue();
2009 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) && format != QLatin1String(
"image/svg+xml" ) )
2014 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format != QLatin1String(
"ttf" ) )
2018 const QDomElement onlineResourceElem = graphicChildElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
2019 const QDomElement inlineContentElem = graphicChildElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
2021 if ( !onlineResourceElem.isNull() )
2023 name = onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) );
2025 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format == QLatin1String(
"ttf" ) )
2028 if ( name.startsWith( QLatin1String(
"ttf://" ) ) )
2029 name = name.mid( 6 );
2032 const QDomElement markIndexElem = graphicChildElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
2033 if ( markIndexElem.isNull() )
2037 const int v = markIndexElem.firstChild().nodeValue().toInt( &ok );
2048 else if ( !inlineContentElem.isNull() )
2058 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2060 name = QStringLiteral(
"square" );
2067 if ( found && graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2074 Qt::BrushStyle markFillStyle;
2076 QDomElement markFillElem = graphicChildElem.firstChildElement( QStringLiteral(
"Fill" ) );
2077 if (
fillFromSld( markFillElem, markFillStyle, fillColor ) )
2082 Qt::PenStyle strokeStyle;
2083 double strokeWidth = 1.0, dashOffset = 0.0;
2084 QVector<qreal> customDashPattern;
2086 QDomElement markStrokeElem = graphicChildElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2087 if (
lineFromSld( markStrokeElem, strokeStyle, strokeColor, strokeWidth,
2088 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2095 const QDomElement opacityElem = graphicElem.firstChildElement( QStringLiteral(
"Opacity" ) );
2096 if ( !opacityElem.isNull() )
2097 fillColor.setAlpha(
decodeSldAlpha( opacityElem.firstChild().nodeValue() ) );
2099 const QDomElement sizeElem = graphicElem.firstChildElement( QStringLiteral(
"Size" ) );
2100 if ( !sizeElem.isNull() )
2103 const double v = sizeElem.firstChild().nodeValue().toDouble( &ok );
2112 const double v = angleFunc.toDouble( &ok );
2122 if ( validFill || validStroke )
2124 if ( format == QLatin1String(
"image/svg+xml" ) )
2127 map[QStringLiteral(
"name" )] = name;
2128 map[QStringLiteral(
"fill" )] = fillColor.name();
2129 map[QStringLiteral(
"outline" )] = strokeColor.name();
2130 map[QStringLiteral(
"outline-width" )] = QString::number( strokeWidth );
2132 map[QStringLiteral(
"size" )] = QString::number( size );
2134 map[QStringLiteral(
"angle" )] = QString::number(
angle );
2135 if ( !offset.isNull() )
2136 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
2139 else if ( format == QLatin1String(
"ttf" ) )
2142 map[QStringLiteral(
"font" )] = name;
2143 map[QStringLiteral(
"chr" )] = markIndex;
2144 map[QStringLiteral(
"color" )] =
encodeColor( validFill ? fillColor : Qt::transparent );
2146 map[QStringLiteral(
"size" )] = QString::number( size );
2148 map[QStringLiteral(
"angle" )] = QString::number(
angle );
2149 if ( !offset.isNull() )
2150 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
2156 if ( layers.isEmpty() )
2159 layerList << layers;
2166 QString patternName;
2167 switch ( brushStyle )
2172 case Qt::SolidPattern:
2173 if ( color.isValid() )
2176 if ( color.alpha() < 255 )
2181 case Qt::CrossPattern:
2182 case Qt::DiagCrossPattern:
2183 case Qt::HorPattern:
2184 case Qt::VerPattern:
2185 case Qt::BDiagPattern:
2186 case Qt::FDiagPattern:
2187 case Qt::Dense1Pattern:
2188 case Qt::Dense2Pattern:
2189 case Qt::Dense3Pattern:
2190 case Qt::Dense4Pattern:
2191 case Qt::Dense5Pattern:
2192 case Qt::Dense6Pattern:
2193 case Qt::Dense7Pattern:
2198 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( brushStyle ) ) );
2202 QDomElement graphicFillElem = doc.createElement( QStringLiteral(
"se:GraphicFill" ) );
2203 element.appendChild( graphicFillElem );
2205 QDomElement graphicElem = doc.createElement( QStringLiteral(
"se:Graphic" ) );
2206 graphicFillElem.appendChild( graphicElem );
2208 const QColor fillColor = patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
2209 const QColor strokeColor = !patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
2212 wellKnownMarkerToSld( doc, graphicElem, patternName, fillColor, strokeColor, Qt::SolidLine, -1, -1 );
2219 brushStyle = Qt::SolidPattern;
2220 color = QColor( 128, 128, 128 );
2222 if ( element.isNull() )
2224 brushStyle = Qt::NoBrush;
2229 const QDomElement graphicFillElem = element.firstChildElement( QStringLiteral(
"GraphicFill" ) );
2231 if ( graphicFillElem.isNull() )
2234 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2236 QgsDebugMsgLevel( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ), 2 );
2238 if ( it.key() == QLatin1String(
"fill" ) )
2239 color = QColor( it.value() );
2240 else if ( it.key() == QLatin1String(
"fill-opacity" ) )
2246 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
2247 if ( graphicElem.isNull() )
2250 QString patternName = QStringLiteral(
"square" );
2251 QColor fillColor, strokeColor;
2252 double strokeWidth, size;
2253 Qt::PenStyle strokeStyle;
2254 if ( !
wellKnownMarkerFromSld( graphicElem, patternName, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
2258 if ( brushStyle == Qt::NoBrush )
2261 const QColor
c = patternName.startsWith( QLatin1String(
"brush://" ) ) ? fillColor : strokeColor;
2270 Qt::PenStyle penStyle,
const QColor &color,
double width,
2271 const Qt::PenJoinStyle *penJoinStyle,
const Qt::PenCapStyle *penCapStyle,
2272 const QVector<qreal> *customDashPattern,
double dashOffset )
2274 QVector<qreal> dashPattern;
2275 const QVector<qreal> *pattern = &dashPattern;
2277 if ( penStyle == Qt::CustomDashLine && !customDashPattern )
2279 element.appendChild( doc.createComment( QStringLiteral(
"WARNING: Custom dash pattern required but not provided. Using default dash pattern." ) ) );
2280 penStyle = Qt::DashLine;
2292 dashPattern.push_back( 4.0 );
2293 dashPattern.push_back( 2.0 );
2296 dashPattern.push_back( 1.0 );
2297 dashPattern.push_back( 2.0 );
2299 case Qt::DashDotLine:
2300 dashPattern.push_back( 4.0 );
2301 dashPattern.push_back( 2.0 );
2302 dashPattern.push_back( 1.0 );
2303 dashPattern.push_back( 2.0 );
2305 case Qt::DashDotDotLine:
2306 dashPattern.push_back( 4.0 );
2307 dashPattern.push_back( 2.0 );
2308 dashPattern.push_back( 1.0 );
2309 dashPattern.push_back( 2.0 );
2310 dashPattern.push_back( 1.0 );
2311 dashPattern.push_back( 2.0 );
2314 case Qt::CustomDashLine:
2315 Q_ASSERT( customDashPattern );
2316 pattern = customDashPattern;
2320 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( penStyle ) ) );
2324 if ( color.isValid() )
2327 if ( color.alpha() < 255 )
2334 else if ( width == 0 )
2344 if ( !pattern->isEmpty() )
2354 Qt::PenStyle &penStyle, QColor &color,
double &width,
2355 Qt::PenJoinStyle *penJoinStyle, Qt::PenCapStyle *penCapStyle,
2356 QVector<qreal> *customDashPattern,
double *dashOffset )
2360 penStyle = Qt::SolidLine;
2361 color = QColor( 0, 0, 0 );
2364 *penJoinStyle = Qt::BevelJoin;
2366 *penCapStyle = Qt::SquareCap;
2367 if ( customDashPattern )
2368 customDashPattern->clear();
2372 if ( element.isNull() )
2374 penStyle = Qt::NoPen;
2380 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2382 QgsDebugMsgLevel( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ), 2 );
2384 if ( it.key() == QLatin1String(
"stroke" ) )
2386 color = QColor( it.value() );
2388 else if ( it.key() == QLatin1String(
"stroke-opacity" ) )
2392 else if ( it.key() == QLatin1String(
"stroke-width" ) )
2395 const double w = it.value().toDouble( &ok );
2399 else if ( it.key() == QLatin1String(
"stroke-linejoin" ) && penJoinStyle )
2403 else if ( it.key() == QLatin1String(
"stroke-linecap" ) && penCapStyle )
2407 else if ( it.key() == QLatin1String(
"stroke-dasharray" ) )
2410 if ( !dashPattern.isEmpty() )
2414 bool dashPatternFound =
false;
2416 if ( dashPattern.count() == 2 )
2418 if ( dashPattern.at( 0 ) == 4.0 &&
2419 dashPattern.at( 1 ) == 2.0 )
2421 penStyle = Qt::DashLine;
2422 dashPatternFound =
true;
2424 else if ( dashPattern.at( 0 ) == 1.0 &&
2425 dashPattern.at( 1 ) == 2.0 )
2427 penStyle = Qt::DotLine;
2428 dashPatternFound =
true;
2431 else if ( dashPattern.count() == 4 )
2433 if ( dashPattern.at( 0 ) == 4.0 &&
2434 dashPattern.at( 1 ) == 2.0 &&
2435 dashPattern.at( 2 ) == 1.0 &&
2436 dashPattern.at( 3 ) == 2.0 )
2438 penStyle = Qt::DashDotLine;
2439 dashPatternFound =
true;
2442 else if ( dashPattern.count() == 6 )
2444 if ( dashPattern.at( 0 ) == 4.0 &&
2445 dashPattern.at( 1 ) == 2.0 &&
2446 dashPattern.at( 2 ) == 1.0 &&
2447 dashPattern.at( 3 ) == 2.0 &&
2448 dashPattern.at( 4 ) == 1.0 &&
2449 dashPattern.at( 5 ) == 2.0 )
2451 penStyle = Qt::DashDotDotLine;
2452 dashPatternFound =
true;
2457 if ( !dashPatternFound )
2459 if ( customDashPattern )
2461 penStyle = Qt::CustomDashLine;
2462 *customDashPattern = dashPattern;
2466 QgsDebugMsgLevel( QStringLiteral(
"custom dash pattern required but not provided. Using default dash pattern." ), 2 );
2467 penStyle = Qt::DashLine;
2472 else if ( it.key() == QLatin1String(
"stroke-dashoffset" ) && dashOffset )
2475 const double d = it.value().toDouble( &ok );
2485 const QString &path,
const QString &mime,
2486 const QColor &color,
double size )
2488 QDomElement externalGraphicElem = doc.createElement( QStringLiteral(
"se:ExternalGraphic" ) );
2489 element.appendChild( externalGraphicElem );
2498 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2500 element.appendChild( sizeElem );
2505 const QString &path,
const QColor &fillColor,
double size,
const QColor &strokeColor,
double strokeWidth )
2512 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Parametric SVG" ) ) );
2513 const QString parametricPath =
getSvgParametricPath( path, fillColor, strokeColor, strokeWidth );
2516 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Plain SVG fallback, no parameters" ) ) );
2519 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Well known marker fallback" ) ) );
2525 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2527 graphicElem.appendChild( sizeElem );
2535 if ( fillColor.isValid() )
2537 url.addQueryItem( QStringLiteral(
"fill" ), fillColor.name() );
2538 url.addQueryItem( QStringLiteral(
"fill-opacity" ),
encodeSldAlpha( fillColor.alpha() ) );
2542 url.addQueryItem( QStringLiteral(
"fill" ), QStringLiteral(
"#000000" ) );
2543 url.addQueryItem( QStringLiteral(
"fill-opacity" ), QStringLiteral(
"1" ) );
2545 if ( strokeColor.isValid() )
2547 url.addQueryItem( QStringLiteral(
"outline" ), strokeColor.name() );
2548 url.addQueryItem( QStringLiteral(
"outline-opacity" ),
encodeSldAlpha( strokeColor.alpha() ) );
2552 url.addQueryItem( QStringLiteral(
"outline" ), QStringLiteral(
"#000000" ) );
2553 url.addQueryItem( QStringLiteral(
"outline-opacity" ), QStringLiteral(
"1" ) );
2555 url.addQueryItem( QStringLiteral(
"outline-width" ), QString::number( strokeWidth ) );
2556 const QString params = url.toString( QUrl::FullyEncoded );
2557 if ( params.isEmpty() )
2563 return basePath +
"?" + params;
2568 QString &path, QString &mime,
2569 QColor &color,
double &size )
2574 QDomElement externalGraphicElem = element.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
2575 if ( externalGraphicElem.isNull() )
2580 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2581 if ( !sizeElem.isNull() )
2584 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2593 const QString &path,
const QString &format,
int *markIndex,
2594 const QColor &color,
double size )
2596 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2597 element.appendChild( markElem );
2603 QDomElement markIndexElem = doc.createElement( QStringLiteral(
"se:MarkIndex" ) );
2604 markIndexElem.appendChild( doc.createTextNode( QString::number( *markIndex ) ) );
2605 markElem.appendChild( markIndexElem );
2609 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2610 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2611 markElem.appendChild( fillElem );
2616 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2618 element.appendChild( sizeElem );
2623 QString &path, QString &format,
int &markIndex,
2624 QColor &color,
double &size )
2632 QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2633 if ( markElem.isNull() )
2638 const QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
2639 if ( !markIndexElem.isNull() )
2642 const int i = markIndexElem.firstChild().nodeValue().toInt( &ok );
2648 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2649 Qt::BrushStyle b = Qt::SolidPattern;
2654 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2655 if ( !sizeElem.isNull() )
2658 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2667 const QString &name,
const QColor &color,
const QColor &strokeColor, Qt::PenStyle strokeStyle,
2668 double strokeWidth,
double size )
2670 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2671 element.appendChild( markElem );
2673 QDomElement wellKnownNameElem = doc.createElement( QStringLiteral(
"se:WellKnownName" ) );
2674 wellKnownNameElem.appendChild( doc.createTextNode( name ) );
2675 markElem.appendChild( wellKnownNameElem );
2678 if ( color.isValid() )
2680 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2681 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2682 markElem.appendChild( fillElem );
2686 if ( strokeColor.isValid() )
2688 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
2689 lineToSld( doc, strokeElem, strokeStyle, strokeColor, strokeWidth );
2690 markElem.appendChild( strokeElem );
2696 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2698 element.appendChild( sizeElem );
2703 QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle,
2704 double &strokeWidth,
double &size )
2708 name = QStringLiteral(
"square" );
2710 strokeColor = QColor( 0, 0, 0 );
2714 const QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2715 if ( markElem.isNull() )
2718 const QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
2719 if ( !wellKnownNameElem.isNull() )
2721 name = wellKnownNameElem.firstChild().nodeValue();
2726 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2727 Qt::BrushStyle b = Qt::SolidPattern;
2732 QDomElement strokeElem = markElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2733 lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth );
2737 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2738 if ( !sizeElem.isNull() )
2741 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2751 if ( !rotationFunc.isEmpty() )
2753 QDomElement rotationElem = doc.createElement( QStringLiteral(
"se:Rotation" ) );
2755 element.appendChild( rotationElem );
2761 QDomElement rotationElem = element.firstChildElement( QStringLiteral(
"Rotation" ) );
2762 if ( !rotationElem.isNull() )
2772 if ( !alphaFunc.isEmpty() )
2774 QDomElement opacityElem = doc.createElement( QStringLiteral(
"se:Opacity" ) );
2776 element.appendChild( opacityElem );
2782 QDomElement opacityElem = element.firstChildElement( QStringLiteral(
"Opacity" ) );
2783 if ( !opacityElem.isNull() )
2792 if ( offset.isNull() )
2795 QDomElement displacementElem = doc.createElement( QStringLiteral(
"se:Displacement" ) );
2796 element.appendChild( displacementElem );
2798 QDomElement dispXElem = doc.createElement( QStringLiteral(
"se:DisplacementX" ) );
2799 dispXElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.x(), 2 ) ) );
2801 QDomElement dispYElem = doc.createElement( QStringLiteral(
"se:DisplacementY" ) );
2802 dispYElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.y(), 2 ) ) );
2804 displacementElem.appendChild( dispXElem );
2805 displacementElem.appendChild( dispYElem );
2812 QDomElement anchorElem = doc.createElement( QStringLiteral(
"se:AnchorPoint" ) );
2813 element.appendChild( anchorElem );
2815 QDomElement anchorXElem = doc.createElement( QStringLiteral(
"se:AnchorPointX" ) );
2816 anchorXElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.x() ) ) );
2818 QDomElement anchorYElem = doc.createElement( QStringLiteral(
"se:AnchorPointY" ) );
2819 anchorYElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.y() ) ) );
2821 anchorElem.appendChild( anchorXElem );
2822 anchorElem.appendChild( anchorYElem );
2827 offset = QPointF( 0, 0 );
2829 const QDomElement displacementElem = element.firstChildElement( QStringLiteral(
"Displacement" ) );
2830 if ( displacementElem.isNull() )
2833 const QDomElement dispXElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementX" ) );
2834 if ( !dispXElem.isNull() )
2837 const double offsetX = dispXElem.firstChild().nodeValue().toDouble( &ok );
2839 offset.setX( offsetX );
2842 const QDomElement dispYElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementY" ) );
2843 if ( !dispYElem.isNull() )
2846 const double offsetY = dispYElem.firstChild().nodeValue().toDouble( &ok );
2848 offset.setY( offsetY );
2855 const QString &label,
const QFont &font,
2856 const QColor &color,
double size )
2858 QDomElement labelElem = doc.createElement( QStringLiteral(
"se:Label" ) );
2859 labelElem.appendChild( doc.createTextNode( label ) );
2860 element.appendChild( labelElem );
2862 QDomElement fontElem = doc.createElement( QStringLiteral(
"se:Font" ) );
2863 element.appendChild( fontElem );
2867 fontElem.appendChild( createSldParameterElement( doc,
"font-style",
encodeSldFontStyle( font.style() ) ) );
2868 fontElem.appendChild( createSldParameterElement( doc,
"font-weight",
encodeSldFontWeight( font.weight() ) ) );
2873 if ( color.isValid() )
2875 QDomElement fillElem = doc.createElement( QStringLiteral(
"Fill" ) );
2876 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2877 element.appendChild( fillElem );
2882 Qt::PenJoinStyle joinStyle,
2883 Qt::PenCapStyle capStyle,
2885 const QVector<qreal> *dashPattern )
2888 penStyle.append(
"PEN(" );
2889 penStyle.append(
"c:" );
2890 penStyle.append(
c.name() );
2891 penStyle.append(
",w:" );
2893 penStyle.append( QString::number( width * mmScaleFactor ) );
2894 penStyle.append(
"mm" );
2897 if ( dashPattern && !dashPattern->isEmpty() )
2899 penStyle.append(
",p:\"" );
2900 QVector<qreal>::const_iterator pIt = dashPattern->constBegin();
2901 for ( ; pIt != dashPattern->constEnd(); ++pIt )
2903 if ( pIt != dashPattern->constBegin() )
2905 penStyle.append(
' ' );
2907 penStyle.append( QString::number( *pIt * mapUnitScaleFactor ) );
2908 penStyle.append(
'g' );
2910 penStyle.append(
'\"' );
2914 penStyle.append(
",cap:" );
2918 penStyle.append(
'p' );
2921 penStyle.append(
'r' );
2925 penStyle.append(
'b' );
2929 penStyle.append(
",j:" );
2930 switch ( joinStyle )
2933 penStyle.append(
'b' );
2936 penStyle.append(
'r' );
2940 penStyle.append(
'm' );
2946 penStyle.append(
",dp:" );
2947 penStyle.append( QString::number( offset * mapUnitScaleFactor ) );
2948 penStyle.append(
'g' );
2951 penStyle.append(
')' );
2958 brushStyle.append(
"BRUSH(" );
2959 brushStyle.append(
"fc:" );
2960 brushStyle.append( fillColor.name() );
2961 brushStyle.append(
')' );
2967 if ( geomFunc.isEmpty() )
2970 QDomElement geometryElem = doc.createElement( QStringLiteral(
"Geometry" ) );
2971 element.appendChild( geometryElem );
3001 QDomElement geometryElem = element.firstChildElement( QStringLiteral(
"Geometry" ) );
3002 if ( geometryElem.isNull() )
3014 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " + function ) );
3018 if ( !filterElem.isNull() )
3019 element.appendChild( filterElem );
3027 if ( function == QLatin1String(
"ELSE" ) )
3030 element.appendChild( filterElem );
3039 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " + function ) );
3043 if ( !filterElem.isNull() )
3044 element.appendChild( filterElem );
3052 QDomElement elem = element;
3053 if ( element.tagName() != QLatin1String(
"Filter" ) )
3055 const QDomNodeList filterNodes = element.elementsByTagName( QStringLiteral(
"Filter" ) );
3056 if ( !filterNodes.isEmpty() )
3058 elem = filterNodes.at( 0 ).toElement();
3062 if ( elem.isNull() )
3087 const QString &path,
const QString &format )
3091 QDomElement onlineResourceElem = doc.createElement( QStringLiteral(
"se:OnlineResource" ) );
3092 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
3093 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:href" ), url );
3094 element.appendChild( onlineResourceElem );
3096 QDomElement formatElem = doc.createElement( QStringLiteral(
"se:Format" ) );
3097 formatElem.appendChild( doc.createTextNode( format ) );
3098 element.appendChild( formatElem );
3105 const QDomElement onlineResourceElem = element.firstChildElement( QStringLiteral(
"OnlineResource" ) );
3106 if ( onlineResourceElem.isNull() )
3109 path = QUrl::fromPercentEncoding( onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) ).toUtf8() );
3111 const QDomElement formatElem = element.firstChildElement( QStringLiteral(
"Format" ) );
3112 if ( formatElem.isNull() )
3115 format = formatElem.firstChild().nodeValue();
3122 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:SvgParameter" ) );
3123 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
3124 nodeElem.appendChild( doc.createTextNode( value ) );
3133 QDomElement paramElem = element.firstChildElement();
3134 while ( !paramElem.isNull() )
3136 if ( paramElem.localName() == QLatin1String(
"SvgParameter" ) || paramElem.localName() == QLatin1String(
"CssParameter" ) )
3138 const QString name = paramElem.attribute( QStringLiteral(
"name" ) );
3139 if ( paramElem.firstChild().nodeType() == QDomNode::TextNode )
3141 value = paramElem.firstChild().nodeValue();
3145 if ( paramElem.firstChild().nodeType() == QDomNode::ElementNode &&
3146 paramElem.firstChild().localName() == QLatin1String(
"Literal" ) )
3149 value = paramElem.firstChild().firstChild().nodeValue();
3153 QgsDebugMsg( QStringLiteral(
"unexpected child of %1" ).arg( paramElem.localName() ) );
3157 if ( !name.isEmpty() && !value.isEmpty() )
3158 params[ name ] = value;
3161 paramElem = paramElem.nextSiblingElement();
3169 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:VendorOption" ) );
3170 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
3171 nodeElem.appendChild( doc.createTextNode( value ) );
3179 QDomElement paramElem = element.firstChildElement( QStringLiteral(
"VendorOption" ) );
3180 while ( !paramElem.isNull() )
3182 const QString name = paramElem.attribute( QStringLiteral(
"name" ) );
3183 const QString value = paramElem.firstChild().nodeValue();
3185 if ( !name.isEmpty() && !value.isEmpty() )
3186 params[ name ] = value;
3188 paramElem = paramElem.nextSiblingElement( QStringLiteral(
"VendorOption" ) );
3198 if ( newSymbols.type() == QVariant::Map )
3200 return newSymbols.toMap();
3207 QDomElement e = element.firstChildElement();
3208 while ( !e.isNull() )
3210 if ( e.tagName() == QLatin1String(
"prop" ) )
3212 const QString propKey = e.attribute( QStringLiteral(
"k" ) );
3213 const QString propValue = e.attribute( QStringLiteral(
"v" ) );
3214 props[propKey] = propValue;
3216 e = e.nextSiblingElement();
3233 QDomElement e = element.firstChildElement();
3235 while ( !e.isNull() )
3237 if ( e.tagName() == QLatin1String(
"symbol" ) )
3241 symbols.insert( e.attribute( QStringLiteral(
"name" ) ), symbol );
3247 e = e.nextSiblingElement();
3254 QStringList subsymbols;
3256 for ( QMap<QString, QgsSymbol *>::iterator it = symbols.begin(); it != symbols.end(); ++it )
3258 if ( it.key()[0] !=
'@' )
3262 subsymbols.append( it.key() );
3264 QStringList parts = it.key().split(
'@' );
3265 if ( parts.count() < 3 )
3267 QgsDebugMsg(
"found subsymbol with invalid name: " + it.key() );
3271 const QString symname = parts[1];
3272 const int symlayer = parts[2].toInt();
3274 if ( !symbols.contains( symname ) )
3276 QgsDebugMsg(
"subsymbol references invalid symbol: " + symname );
3284 QgsDebugMsg(
"subsymbol references invalid symbol layer: " + QString::number( symlayer ) );
3293 QgsDebugMsg(
"symbol layer refused subsymbol: " + it.key() );
3300 for (
int i = 0; i < subsymbols.count(); i++ )
3301 symbols.take( subsymbols[i] );
3308 QDomElement symbolsElem = doc.createElement( tagName );
3311 for ( QMap<QString, QgsSymbol *>::iterator its = symbols.begin(); its != symbols.end(); ++its )
3313 const QDomElement symEl =
saveSymbol( its.key(), its.value(), doc, context );
3314 symbolsElem.appendChild( symEl );
3322 qDeleteAll( symbols );
3331 std::unique_ptr< QMimeData >mimeData(
new QMimeData );
3333 QDomDocument symbolDoc;
3335 symbolDoc.appendChild( symbolElem );
3336 mimeData->setText( symbolDoc.toString() );
3339 mimeData->setColorData( symbol->
color() );
3341 return mimeData.release();
3349 const QString text = data->text();
3350 if ( !text.isEmpty() )
3355 if ( doc.setContent( text ) )
3357 elem = doc.documentElement();
3359 if ( elem.nodeName() != QLatin1String(
"symbol" ) )
3360 elem = elem.firstChildElement( QStringLiteral(
"symbol" ) );
3371 const QString rampType = element.attribute( QStringLiteral(
"type" ) );
3388 QgsDebugMsg(
"unknown colorramp type " + rampType );
3396 QDomElement rampEl = doc.createElement( QStringLiteral(
"colorramp" ) );
3397 rampEl.setAttribute( QStringLiteral(
"type" ), ramp->
type() );
3398 rampEl.setAttribute( QStringLiteral(
"name" ), name );
3406 QVariantMap rampMap;
3408 rampMap.insert( QStringLiteral(
"type" ), ramp->
type() );
3409 rampMap.insert( QStringLiteral(
"name" ), name );
3411 const QVariantMap properties = ramp->
properties();
3413 QVariantMap propertyMap;
3414 for (
auto property = properties.constBegin(); property != properties.constEnd(); ++property )
3416 propertyMap.insert( property.key(), property.value() );
3419 rampMap.insert( QStringLiteral(
"properties" ), propertyMap );
3425 const QVariantMap rampMap = value.toMap();
3427 const QString rampType = rampMap.
value( QStringLiteral(
"type" ) ).toString();
3430 const QVariantMap propertyMap = rampMap.value( QStringLiteral(
"properties" ) ).toMap();
3433 for (
auto property = propertyMap.constBegin(); property != propertyMap.constEnd(); ++property )
3435 props.insert( property.key(), property.value().toString() );
3450 QgsDebugMsg(
"unknown colorramp type " + rampType );
3457 if ( !color.isValid() )
3464 return color.name();
3469 QList<QColor> colors;
3472 const thread_local QRegularExpression sepCommaSpaceRegExp(
"(,|\\s)" );
3473 QStringList components = colorStr.simplified().split( sepCommaSpaceRegExp );
3474 QStringList::iterator it = components.begin();
3475 for ( ; it != components.end(); ++it )
3477 const QColor result =
parseColor( *it,
true );
3478 if ( result.isValid() )
3483 if ( colors.length() > 0 )
3489 const thread_local QRegularExpression sepCommaRegExp(
"(,|\n)" );
3490 components = colorStr.split( sepCommaRegExp );
3491 it = components.begin();
3492 for ( ; it != components.end(); ++it )
3494 const QColor result =
parseColor( *it,
true );
3495 if ( result.isValid() )
3500 if ( colors.length() > 0 )
3506 components = colorStr.simplified().split( QString(
' ' ) );
3507 it = components.begin();
3508 for ( ; it != components.end(); ++it )
3510 const QColor result =
parseColor( *it,
true );
3511 if ( result.isValid() )
3516 if ( colors.length() > 0 )
3522 components = colorStr.split(
'\n' );
3523 it = components.begin();
3524 for ( ; it != components.end(); ++it )
3526 const QColor result =
parseColor( *it,
true );
3527 if ( result.isValid() )
3540 QMimeData *mimeData =
new QMimeData;
3541 mimeData->setColorData( QVariant( color ) );
3542 mimeData->setText( color.name() );
3549 if ( mimeData->hasColor() )
3551 QColor mimeColor = mimeData->colorData().value<QColor>();
3552 if ( mimeColor.isValid() )
3560 if ( mimeData->hasText() )
3564 if ( textColor.isValid() )
3579 if ( data->hasFormat( QStringLiteral(
"text/xml" ) ) )
3582 const QByteArray encodedData = data->data( QStringLiteral(
"text/xml" ) );
3583 QDomDocument xmlDoc;
3584 xmlDoc.setContent( encodedData );
3586 const QDomElement dragDataElem = xmlDoc.documentElement();
3587 if ( dragDataElem.tagName() == QLatin1String(
"ColorSchemeModelDragData" ) )
3589 const QDomNodeList nodeList = dragDataElem.childNodes();
3590 const int nChildNodes = nodeList.size();
3591 QDomElement currentElem;
3593 for (
int i = 0; i < nChildNodes; ++i )
3595 currentElem = nodeList.at( i ).toElement();
3596 if ( currentElem.isNull() )
3601 QPair< QColor, QString> namedColor;
3603 namedColor.second = currentElem.attribute( QStringLiteral(
"label" ), QString() );
3605 mimeColors << namedColor;
3610 if ( mimeColors.length() == 0 && data->hasFormat( QStringLiteral(
"application/x-colorobject-list" ) ) )
3613 const QByteArray encodedData = data->data( QStringLiteral(
"application/x-colorobject-list" ) );
3614 QDomDocument xmlDoc;
3615 xmlDoc.setContent( encodedData );
3617 const QDomNodeList colorsNodes = xmlDoc.elementsByTagName( QStringLiteral(
"colors" ) );
3618 if ( colorsNodes.length() > 0 )
3620 const QDomElement colorsElem = colorsNodes.at( 0 ).toElement();
3621 const QDomNodeList colorNodeList = colorsElem.childNodes();
3622 const int nChildNodes = colorNodeList.size();
3623 QDomElement currentElem;
3625 for (
int i = 0; i < nChildNodes; ++i )
3628 currentElem = colorNodeList.at( i ).toElement();
3629 if ( currentElem.isNull() )
3634 const QDomNodeList colorNodes = currentElem.elementsByTagName( QStringLiteral(
"color" ) );
3635 const QDomNodeList nameNodes = currentElem.elementsByTagName( QStringLiteral(
"name" ) );
3637 if ( colorNodes.length() > 0 )
3639 const QDomElement colorElem = colorNodes.at( 0 ).toElement();
3641 const QStringList colorParts = colorElem.text().simplified().split(
' ' );
3642 if ( colorParts.length() < 3 )
3647 const int red = colorParts.at( 0 ).toDouble() * 255;
3648 const int green = colorParts.at( 1 ).toDouble() * 255;
3649 const int blue = colorParts.at( 2 ).toDouble() * 255;
3650 QPair< QColor, QString> namedColor;
3651 namedColor.first = QColor( red, green, blue );
3652 if ( nameNodes.length() > 0 )
3654 const QDomElement nameElem = nameNodes.at( 0 ).toElement();
3655 namedColor.second = nameElem.text();
3657 mimeColors << namedColor;
3663 if ( mimeColors.length() == 0 && data->hasText() )
3667 QList< QColor >::iterator it = parsedColors.begin();
3668 for ( ; it != parsedColors.end(); ++it )
3670 mimeColors << qMakePair( *it, QString() );
3674 if ( mimeColors.length() == 0 && data->hasColor() )
3677 const QColor mimeColor = data->colorData().value<QColor>();
3678 if ( mimeColor.isValid() )
3680 mimeColors << qMakePair( mimeColor, QString() );
3690 QMimeData *mimeData =
new QMimeData();
3691 QDomDocument xmlDoc;
3692 QDomElement xmlRootElement = xmlDoc.createElement( QStringLiteral(
"ColorSchemeModelDragData" ) );
3693 xmlDoc.appendChild( xmlRootElement );
3695 QgsNamedColorList::const_iterator colorIt = colorList.constBegin();
3696 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3698 QDomElement namedColor = xmlDoc.createElement( QStringLiteral(
"NamedColor" ) );
3700 namedColor.setAttribute( QStringLiteral(
"label" ), ( *colorIt ).second );
3701 xmlRootElement.appendChild( namedColor );
3703 mimeData->setData( QStringLiteral(
"text/xml" ), xmlDoc.toByteArray() );
3711 colorIt = colorList.constBegin();
3712 QStringList colorListString;
3713 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3715 colorListString << ( *colorIt ).first.name();
3717 mimeData->setText( colorListString.join( QLatin1Char(
'\n' ) ) );
3720 if ( colorList.length() > 0 )
3722 mimeData->setColorData( QVariant( colorList.at( 0 ).first ) );
3730 if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3735 QTextStream stream( &file );
3736 stream <<
"GIMP Palette" << Qt::endl;
3737 if ( paletteName.isEmpty() )
3739 stream <<
"Name: QGIS Palette" << Qt::endl;
3743 stream <<
"Name: " << paletteName << Qt::endl;
3745 stream <<
"Columns: 4" << Qt::endl;
3746 stream <<
'#' << Qt::endl;
3748 for ( QgsNamedColorList::ConstIterator colorIt = colors.constBegin(); colorIt != colors.constEnd(); ++colorIt )
3750 const QColor color = ( *colorIt ).first;
3751 if ( !color.isValid() )
3755 stream << QStringLiteral(
"%1 %2 %3" ).arg( color.red(), 3 ).arg( color.green(), 3 ).arg( color.blue(), 3 );
3756 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << Qt::endl;
3767 if ( !file.open( QIODevice::ReadOnly ) )
3770 return importedColors;
3773 QTextStream in( &file );
3775 QString line = in.readLine();
3776 if ( !line.startsWith( QLatin1String(
"GIMP Palette" ) ) )
3779 return importedColors;
3783 while ( !in.atEnd() && !line.startsWith( QLatin1String(
"Name:" ) ) && !line.startsWith(
'#' ) )
3785 line = in.readLine();
3787 if ( line.startsWith( QLatin1String(
"Name:" ) ) )
3789 const thread_local QRegularExpression nameRx(
"Name:\\s*(\\S.*)$" );
3790 const QRegularExpressionMatch match = nameRx.match( line );
3791 if ( match.hasMatch() )
3793 name = match.captured( 1 );
3798 while ( !in.atEnd() && !line.startsWith(
'#' ) )
3800 line = in.readLine();
3805 return importedColors;
3809 const thread_local QRegularExpression rx(
"^\\s*(\\d+)\\s+(\\d+)\\s+(\\d+)(\\s.*)?$" );
3810 while ( !in.atEnd() )
3812 line = in.readLine();
3813 const QRegularExpressionMatch match = rx.match( line );
3814 if ( !match.hasMatch() )
3818 const int red = match.captured( 1 ).toInt();
3819 const int green = match.captured( 2 ).toInt();
3820 const int blue = match.captured( 3 ).toInt();
3821 const QColor color = QColor( red, green, blue );
3822 if ( !color.isValid() )
3829 if ( rx.captureCount() > 3 )
3831 label = match.captured( 4 ).simplified();
3838 importedColors << qMakePair( color, label );
3843 return importedColors;
3856 const thread_local QRegularExpression hexColorAlphaRx(
"^\\s*#?([0-9a-fA-F]{6})([0-9a-fA-F]{2})\\s*$" );
3857 QRegularExpressionMatch match = hexColorAlphaRx.match( colorStr );
3860 if ( !match.hasMatch() && QColor::isValidColor( colorStr ) )
3863 parsedColor.setNamedColor( colorStr );
3864 if ( parsedColor.isValid() )
3866 containsAlpha =
false;
3872 if ( match.hasMatch() )
3874 const QString hexColor = match.captured( 1 );
3875 parsedColor.setNamedColor( QStringLiteral(
"#" ) + hexColor );
3877 const int alphaHex = match.captured( 2 ).toInt( &alphaOk, 16 );
3879 if ( parsedColor.isValid() && alphaOk )
3881 parsedColor.setAlpha( alphaHex );
3882 containsAlpha =
true;
3890 const thread_local QRegularExpression hexColorRx2(
"^\\s*(?:[0-9a-fA-F]{3}){1,2}\\s*$" );
3891 if ( colorStr.indexOf( hexColorRx2 ) != -1 )
3894 parsedColor.setNamedColor( QStringLiteral(
"#" ) + colorStr );
3895 if ( parsedColor.isValid() )
3897 containsAlpha =
false;
3904 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*$" );
3905 match = rgbFormatRx.match( colorStr );
3906 if ( match.hasMatch() )
3908 const int r = match.captured( 1 ).toInt();
3909 const int g = match.captured( 2 ).toInt();
3910 const int b = match.captured( 3 ).toInt();
3911 parsedColor.setRgb( r, g, b );
3912 if ( parsedColor.isValid() )
3914 containsAlpha =
false;
3920 const thread_local QRegularExpression hslFormatRx(
"^\\s*hsl\\(?\\s*(\\d+)\\s*,\\s*(\\d+)\\s*%\\s*,\\s*(\\d+)\\s*%\\s*\\)?\\s*;?\\s*$" );
3921 match = hslFormatRx.match( colorStr );
3922 if ( match.hasMatch() )
3924 const int h = match.captured( 1 ).toInt();
3925 const int s = match.captured( 2 ).toInt();
3926 const int l = match.captured( 3 ).toInt();
3927 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0 );
3928 if ( parsedColor.isValid() )
3930 containsAlpha =
false;
3936 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*$" );
3937 match = rgbPercentFormatRx.match( colorStr );
3938 if ( match.hasMatch() )
3940 const int r = std::round( match.captured( 1 ).toDouble() * 2.55 );
3941 const int g = std::round( match.captured( 2 ).toDouble() * 2.55 );
3942 const int b = std::round( match.captured( 3 ).toDouble() * 2.55 );
3943 parsedColor.setRgb( r, g, b );
3944 if ( parsedColor.isValid() )
3946 containsAlpha =
false;
3952 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*$" );
3953 match = rgbaFormatRx.match( colorStr );
3954 if ( match.hasMatch() )
3956 const int r = match.captured( 1 ).toInt();
3957 const int g = match.captured( 2 ).toInt();
3958 const int b = match.captured( 3 ).toInt();
3959 const int a = std::round( match.captured( 4 ).toDouble() * 255.0 );
3960 parsedColor.setRgb( r, g, b, a );
3961 if ( parsedColor.isValid() )
3963 containsAlpha =
true;
3969 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*$" );
3970 match = rgbaPercentFormatRx.match( colorStr );
3971 if ( match.hasMatch() )
3973 const int r = std::round( match.captured( 1 ).toDouble() * 2.55 );
3974 const int g = std::round( match.captured( 2 ).toDouble() * 2.55 );
3975 const int b = std::round( match.captured( 3 ).toDouble() * 2.55 );
3976 const int a = std::round( match.captured( 4 ).toDouble() * 255.0 );
3977 parsedColor.setRgb( r, g, b, a );
3978 if ( parsedColor.isValid() )
3980 containsAlpha =
true;
3986 const thread_local QRegularExpression hslaPercentFormatRx(
"^\\s*hsla\\(?\\s*(\\d+)\\s*,\\s*(\\d+)\\s*%\\s*,\\s*(\\d+)\\s*%\\s*,\\s*([\\d\\.]+)\\s*\\)?\\s*;?\\s*$" );
3987 match = hslaPercentFormatRx.match( colorStr );
3988 if ( match.hasMatch() )
3990 const int h = match.captured( 1 ).toInt();
3991 const int s = match.captured( 2 ).toInt();
3992 const int l = match.captured( 3 ).toInt();
3993 const int a = std::round( match.captured( 4 ).toDouble() * 255.0 );
3994 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0, a );
3995 if ( parsedColor.isValid() )
3997 containsAlpha =
true;
4014 const QImage::Format format = image->format();
4015 if ( format != QImage::Format_ARGB32_Premultiplied && format != QImage::Format_ARGB32 )
4017 QgsDebugMsg( QStringLiteral(
"no alpha channel." ) );
4022 for (
int heightIndex = 0; heightIndex < image->height(); ++heightIndex )
4024 QRgb *scanLine =
reinterpret_cast< QRgb *
>( image->scanLine( heightIndex ) );
4025 for (
int widthIndex = 0; widthIndex < image->width(); ++widthIndex )
4027 myRgb = scanLine[widthIndex];
4028 if ( format == QImage::Format_ARGB32_Premultiplied )
4029 scanLine[widthIndex] = qRgba( opacity * qRed( myRgb ), opacity * qGreen( myRgb ), opacity * qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4031 scanLine[widthIndex] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4039 const int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
4040 const int alpha = ( radius < 1 ) ? 16 : ( radius > 17 ) ? 1 : tab[radius - 1];
4042 if ( image.format() != QImage::Format_ARGB32_Premultiplied
4043 && image.format() != QImage::Format_RGB32 )
4045 image = image.convertToFormat( QImage::Format_ARGB32_Premultiplied );
4048 const int r1 = rect.top();
4049 const int r2 = rect.bottom();
4050 const int c1 = rect.left();
4051 const int c2 = rect.right();
4053 const int bpl = image.bytesPerLine();
4061 i1 = i2 = ( QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3 );
4063 for (
int col = c1; col <= c2; col++ )
4065 p = image.scanLine( r1 ) + col * 4;
4066 for (
int i = i1; i <= i2; i++ )
4067 rgba[i] = p[i] << 4;
4070 for (
int j = r1; j < r2; j++, p += bpl )
4071 for (
int i = i1; i <= i2; i++ )
4072 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4075 for (
int row = r1; row <= r2; row++ )
4077 p = image.scanLine( row ) + c1 * 4;
4078 for (
int i = i1; i <= i2; i++ )
4079 rgba[i] = p[i] << 4;
4082 for (
int j = c1; j < c2; j++, p += 4 )
4083 for (
int i = i1; i <= i2; i++ )
4084 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4087 for (
int col = c1; col <= c2; col++ )
4089 p = image.scanLine( r2 ) + col * 4;
4090 for (
int i = i1; i <= i2; i++ )
4091 rgba[i] = p[i] << 4;
4094 for (
int j = r1; j < r2; j++, p -= bpl )
4095 for (
int i = i1; i <= i2; i++ )
4096 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4099 for (
int row = r1; row <= r2; row++ )
4101 p = image.scanLine( row ) + c2 * 4;
4102 for (
int i = i1; i <= i2; i++ )
4103 rgba[i] = p[i] << 4;
4106 for (
int j = c1; j < c2; j++, p -= 4 )
4107 for (
int i = i1; i <= i2; i++ )
4108 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4114 if ( alpha != 255 && alpha > 0 )
4118 const double alphaFactor = alpha / 255.;
4119 int r = 0, g = 0, b = 0;
4120 rgb.getRgb( &r, &g, &b );
4125 rgb.setRgb( r, g, b, alpha );
4127 else if ( alpha == 0 )
4129 rgb.setRgb( 0, 0, 0, 0 );
4138 if ( !simpleFill || !simpleLine )
4162 if ( simpleLine->
offset() )
4180 if ( order == Qt::AscendingOrder )
4194 const double dx = directionPoint.x() - startPoint.x();
4195 const double dy = directionPoint.y() - startPoint.y();
4196 const double length = std::sqrt( dx * dx + dy * dy );
4197 const double scaleFactor = distance / length;
4198 return QPointF( startPoint.x() + dx * scaleFactor, startPoint.y() + dy * scaleFactor );
4208 for (
int i = 0; i < svgPaths.size(); i++ )
4210 const QDir dir( svgPaths[i] );
4211 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4212 for (
const QString &item : svgSubPaths )
4214 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4217 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4218 for (
const QString &item : svgFiles )
4221 list.append( dir.path() +
'/' + item );
4233 QStringList svgPaths;
4234 svgPaths.append( directory );
4236 for (
int i = 0; i < svgPaths.size(); i++ )
4238 const QDir dir( svgPaths[i] );
4239 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4240 for (
const QString &item : svgSubPaths )
4242 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4245 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4246 for (
const QString &item : svgFiles )
4248 list.append( dir.path() +
'/' + item );
4260 if ( n.startsWith( QLatin1String(
"base64:" ) ) )
4264 if ( QFileInfo::exists( n ) )
4265 return QFileInfo( n ).canonicalFilePath();
4269 if ( name.contains( QLatin1String(
"://" ) ) )
4271 const QUrl url( name );
4272 if ( url.isValid() && !url.scheme().isEmpty() )
4274 if ( url.scheme().compare( QLatin1String(
"file" ), Qt::CaseInsensitive ) == 0 )
4277 name = url.toLocalFile();
4278 if ( QFile( name ).exists() )
4280 return QFileInfo( name ).canonicalFilePath();
4294 for (
int i = 0; i < svgPaths.size(); i++ )
4296 QString svgPath = svgPaths[i];
4297 if ( svgPath.endsWith( QChar(
'/' ) ) )
4308 const QString myLocalPath = svgPath + QDir::separator() + name;
4311 if ( QFile( myLocalPath ).exists() )
4314 return QFileInfo( myLocalPath ).canonicalFilePath();
4318 return pathResolver.
readPath( name );
4326 if ( p.startsWith( QLatin1String(
"base64:" ) ) )
4329 if ( !QFileInfo::exists( p ) )
4332 QString path = QFileInfo( p ).canonicalFilePath();
4336 bool isInSvgPaths =
false;
4337 for (
int i = 0; i < svgPaths.size(); i++ )
4339 const QString dir = QFileInfo( svgPaths[i] ).canonicalFilePath();
4341 if ( !dir.isEmpty() && path.startsWith( dir ) )
4343 path = path.mid( dir.size() + 1 );
4344 isInSvgPaths =
true;
4359 double cx = 0, cy = 0;
4360 double area, sum = 0;
4361 for (
int i = points.count() - 1, j = 0; j < points.count(); i = j++ )
4363 const QPointF &p1 = points[i];
4364 const QPointF &p2 = points[j];
4365 area = p1.x() * p2.y() - p1.y() * p2.x();
4367 cx += ( p1.x() + p2.x() ) * area;
4368 cy += ( p1.y() + p2.y() ) * area;
4375 if ( points.count() >= 2 )
4376 return QPointF( ( points[0].x() + points[1].x() ) / 2, ( points[0].y() + points[1].y() ) / 2 );
4377 else if ( points.count() == 1 )
4385 return QPointF( cx, cy );
4394 unsigned int i, pointCount = points.count();
4396 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( points[i].x(), points[i].y() );
4402 for (
auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
4404 pointCount = ( *ringIt ).count();
4406 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( ( *ringIt )[i].x(), ( *ringIt )[i].y() );
4412 if ( !pointOnSurfaceGeom.
isNull() )
4426 bool inside =
false;
4428 const double x = point.x();
4429 const double y = point.y();
4431 for (
int i = 0, j = points.count() - 1; i < points.count(); i++ )
4433 const QPointF &p1 = points[i];
4434 const QPointF &p2 = points[j];
4439 if ( ( p1.y() < y && p2.y() >= y ) || ( p2.y() < y && p1.y() >= y ) )
4441 if ( p1.x() + ( y - p1.y() ) / ( p2.y() - p1.y() ) * ( p2.x() - p1.x() ) <= x )
4452 if ( polyline.size() < 2 )
4455 double totalLength = 0;
4456 auto it = polyline.begin();
4458 for ( ; it != polyline.end(); ++it )
4460 const QPointF p2 = *it;
4461 const double segmentLength = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4462 totalLength += segmentLength;
4470 if ( polyline.size() < 2 )
4473 double totalLength = 0;
4474 auto it = polyline.begin();
4476 std::vector< double > segmentLengths( polyline.size() - 1 );
4477 auto segmentLengthIt = segmentLengths.begin();
4478 for ( ; it != polyline.end(); ++it )
4480 const QPointF p2 = *it;
4481 *segmentLengthIt = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4482 totalLength += *segmentLengthIt;
4488 if ( startOffset >= 0 && totalLength <= startOffset )
4490 if ( endOffset < 0 && totalLength <= -endOffset )
4493 const double startDistance = startOffset < 0 ? totalLength + startOffset : startOffset;
4494 const double endDistance = endOffset <= 0 ? totalLength + endOffset : endOffset;
4495 QPolygonF substringPoints;
4496 substringPoints.reserve( polyline.size() );
4498 it = polyline.begin();
4499 segmentLengthIt = segmentLengths.begin();
4502 bool foundStart =
false;
4503 if (
qgsDoubleNear( startDistance, 0.0 ) || startDistance < 0 )
4505 substringPoints << p1;
4509 double distanceTraversed = 0;
4510 for ( ; it != polyline.end(); ++it )
4512 const QPointF p2 = *it;
4513 if ( distanceTraversed < startDistance && distanceTraversed + *segmentLengthIt > startDistance )
4516 const double distanceToStart = startDistance - distanceTraversed;
4517 double startX, startY;
4519 substringPoints << QPointF( startX, startY );
4522 if ( foundStart && ( distanceTraversed + *segmentLengthIt > endDistance ) )
4525 const double distanceToEnd = endDistance - distanceTraversed;
4528 if ( substringPoints.last() != QPointF( endX, endY ) )
4529 substringPoints << QPointF( endX, endY );
4531 else if ( foundStart )
4533 if ( substringPoints.last() != QPointF( p2.x(), p2.y() ) )
4534 substringPoints << QPointF( p2.x(), p2.y() );
4537 distanceTraversed += *segmentLengthIt;
4538 if ( distanceTraversed > endDistance )
4545 if ( ( substringPoints.size() < 2 ) || ( substringPoints.size() == 2 && substringPoints.at( 0 ) == substringPoints.at( 1 ) ) )
4548 return substringPoints;
4553 double vertexAngle = M_PI - ( std::atan2( p3.y() - p2.y(), p3.x() - p2.x() ) - std::atan2( p2.y() - p1.y(), p2.x() - p1.x() ) );
4557 return vertexAngle < M_PI * 135.0 / 180.0 || vertexAngle > M_PI * 225.0 / 180.0;
4562 target.reserve( target.size() + line.size() );
4563 for (
const QPointF &pt : line )
4565 if ( !target.empty() && target.last() == pt )
4574 if ( fieldOrExpression.isEmpty() )
4609 QList<double> breaks;
4612 breaks.append( maximum );
4616 const int minimumCount =
static_cast< int >( classes ) / 3;
4617 const double shrink = 0.75;
4618 const double highBias = 1.5;
4619 const double adjustBias = 0.5 + 1.5 * highBias;
4620 const int divisions = classes;
4621 const double h = highBias;
4624 const double dx = maximum - minimum;
4634 cell = std::max( std::fabs( minimum ), std::fabs( maximum ) );
4635 if ( adjustBias >= 1.5 * h + 0.5 )
4637 U = 1 + ( 1.0 / ( 1 + h ) );
4641 U = 1 + ( 1.5 / ( 1 + adjustBias ) );
4643 small = dx < ( cell * U * std::max( 1, divisions ) * 1e-07 * 3.0 );
4650 cell = 9 + cell / 10;
4651 cell = cell * shrink;
4653 if ( minimumCount > 1 )
4655 cell = cell / minimumCount;
4661 if ( divisions > 1 )
4663 cell = cell / divisions;
4666 if ( cell < 20 * 1e-07 )
4671 const double base = std::pow( 10.0, std::floor( std::log10( cell ) ) );
4673 if ( ( 2 * base ) - cell < h * ( cell - unit ) )
4676 if ( ( 5 * base ) - cell < adjustBias * ( cell - unit ) )
4679 if ( ( 10.0 * base ) - cell < h * ( cell - unit ) )
4686 int start = std::floor( minimum / unit + 1e-07 );
4687 int end = std::ceil( maximum / unit - 1e-07 );
4690 while ( start * unit > minimum + ( 1e-07 * unit ) )
4694 while ( end * unit < maximum - ( 1e-07 * unit ) )
4702 int k = std::floor( 0.5 + end - start );
4703 if ( k < minimumCount )
4705 k = minimumCount - k;
4709 start = start - k / 2 + k % 2;
4713 start = start - k / 2;
4714 end = end + k / 2 + k % 2;
4717 const double minimumBreak = start * unit;
4719 const int count = end - start;
4721 breaks.reserve( count );
4722 for (
int i = 1; i < count + 1; i++ )
4724 breaks.append( minimumBreak + i * unit );
4727 if ( breaks.isEmpty() )
4730 if ( breaks.first() < minimum )
4732 breaks[0] = minimum;
4734 if ( breaks.last() > maximum )
4736 breaks[breaks.count() - 1] = maximum;
4741 if ( minimum < 0.0 && maximum > 0.0 )
4743 QList<double> breaksMinusZero;
4744 for (
int i = 0; i < breaks.count(); i++ )
4746 breaksMinusZero.append( breaks[i] - 0.0 );
4749 for (
int i = 1; i < breaks.count(); i++ )
4751 if ( std::abs( breaksMinusZero[i] ) < std::abs( breaksMinusZero[i - 1] ) )
4754 breaks[posOfMin] = 0.0;
4763 bool roundToUnit =
false;
4764 if ( unit == Qgis::RenderUnit::Unknown )
4766 if ( props.contains( QStringLiteral(
"uomScale" ) ) )
4769 scale = props.value( QStringLiteral(
"uomScale" ) ).toDouble( &ok );
4778 if ( props.value( QStringLiteral(
"uom" ) ) == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
4782 case Qgis::RenderUnit::Millimeters:
4785 case Qgis::RenderUnit::Pixels:
4798 case Qgis::RenderUnit::Millimeters:
4802 case Qgis::RenderUnit::Inches:
4803 scale = 1 / 0.28 * 25.4;
4806 case Qgis::RenderUnit::Points:
4810 case Qgis::RenderUnit::Pixels:
4814 case Qgis::RenderUnit::MapUnits:
4815 case Qgis::RenderUnit::MetersInMapUnits:
4819 case Qgis::RenderUnit::Percentage:
4820 case Qgis::RenderUnit::Unknown:
4827 double rescaled = size * scale;
4832 rescaled = std::round( rescaled );
4839 const double x =
rescaleUom( point.x(), unit, props );
4840 const double y =
rescaleUom( point.y(), unit, props );
4841 return QPointF( x, y );
4846 QVector<qreal> result;
4847 QVector<qreal>::const_iterator it = array.constBegin();
4848 for ( ; it != array.constEnd(); ++it )
4850 result.append(
rescaleUom( *it, unit, props ) );
4857 if ( !props.value( QStringLiteral(
"scaleMinDenom" ), QString() ).toString().isEmpty() )
4859 QDomElement scaleMinDenomElem = doc.createElement( QStringLiteral(
"se:MinScaleDenominator" ) );
4860 scaleMinDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMinDenom" ) ).toString().toDouble() ) ) );
4861 ruleElem.appendChild( scaleMinDenomElem );
4864 if ( !props.value( QStringLiteral(
"scaleMaxDenom" ), QString() ).toString().isEmpty() )
4866 QDomElement scaleMaxDenomElem = doc.createElement( QStringLiteral(
"se:MaxScaleDenominator" ) );
4867 scaleMaxDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMaxDenom" ) ).toString().toDouble() ) ) );
4868 ruleElem.appendChild( scaleMaxDenomElem );
4877 const double parentScaleMinDenom = props.value( QStringLiteral(
"scaleMinDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
4878 if ( !ok || parentScaleMinDenom <= 0 )
4879 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( mScaleMinDenom );
4881 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( std::max( parentScaleMinDenom, mScaleMinDenom ) );
4887 const double parentScaleMaxDenom = props.value( QStringLiteral(
"scaleMaxDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
4888 if ( !ok || parentScaleMaxDenom <= 0 )
4889 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( mScaleMaxDenom );
4891 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( std::min( parentScaleMaxDenom, mScaleMaxDenom ) );
4899 if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
4901 scale = 1.0 / 0.00028;
4903 else if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
4905 scale = 304.8 / 0.28;
4912 return size * scale;
4920 SymbolLayerVisitor(
const QSet<QgsSymbolLayerId> &layerIds )
4921 : mSymbolLayerIds( layerIds )
4934 void visitSymbol(
const QgsSymbol *symbol,
const QString &identifier, QVector<int> rootPath )
4938 QVector<int> indexPath = rootPath;
4939 indexPath.append( idx );
4941 if ( mSymbolLayerIds.contains(
QgsSymbolLayerId( mCurrentRuleKey + identifier, indexPath ) ) )
4943 mSymbolLayers.insert( sl );
4948 visitSymbol( subSymbol, identifier, indexPath );
4957 if ( symbolEntity->symbol() )
4959 visitSymbol( symbolEntity->symbol(), leaf.
identifier, {} );
4965 QString mCurrentRuleKey;
4966 const QSet<QgsSymbolLayerId> &mSymbolLayerIds;
4967 QSet<const QgsSymbolLayer *> mSymbolLayers;
4970 SymbolLayerVisitor visitor( symbolLayerIds );
4971 renderer->
accept( &visitor );
4972 return visitor.mSymbolLayers;
4980 SymbolRefreshRateVisitor()
4992 void visitSymbol(
const QgsSymbol *symbol )
5009 if ( refreshRate == -1 || ( animatedMarker->frameRate() > refreshRate ) )
5010 refreshRate = animatedMarker->frameRate();
5014 visitSymbol( subSymbol );
5022 if (
QgsSymbol *symbol = qgis::down_cast<const QgsStyleSymbolEntity *>( leaf.
entity )->symbol() )
5024 visitSymbol( symbol );
5030 double refreshRate = -1;
5033 SymbolRefreshRateVisitor visitor;
5034 renderer->
accept( &visitor );
5035 return visitor.refreshRate;
5040 if ( !s || !context )
5066 size = markerSymbol->
size( *context );
5068 else if ( lineSymbol )
5070 size = lineSymbol->
width( *context );
5082 if ( minSize > 0 && size < minSize )
5086 else if ( maxSize > 0 && size > maxSize )
5105 else if ( lineSymbol )
5120 QMap<QString, QgsProperty>::const_iterator paramIt = propertiesMap.constBegin();
5121 for ( ; paramIt != propertiesMap.constEnd(); ++paramIt )
5123 properties.insert( paramIt.key(), paramIt.value().valueAsString( context ) );
5131 angleRad = std::fmod( angleRad, M_PI * 2 );
5135 angleRad += M_PI * 2;
5139 struct rationalTangent
5151 static const QList<rationalTangent> __rationalTangents
5153 { 1, 57, 0.01754206006 },
5154 { 3, 86, 0.03486958155 },
5155 { 1, 19, 0.05258306161 },
5156 { 3, 43, 0.06965457373 },
5157 { 7, 80, 0.08727771295 },
5158 { 2, 19, 0.1048769387 },
5159 { 7, 57, 0.1221951707 },
5160 { 9, 64, 0.1397088743 },
5161 { 13, 82, 0.157228051 },
5162 { 3, 17, 0.174672199 },
5163 { 7, 36, 0.1920480172 },
5164 { 17, 80, 0.209385393 },
5165 { 3, 13, 0.2267988481 },
5166 { 1, 4, 0.2449786631 },
5167 { 26, 97, 0.2618852647 },
5168 { 27, 94, 0.2797041525 },
5169 { 26, 85, 0.2968446734 },
5170 { 13, 40, 0.3142318991 },
5171 { 21, 61, 0.3315541619 },
5172 { 4, 11, 0.3487710036 },
5173 { 38, 99, 0.3664967859 },
5174 { 40, 99, 0.383984624 },
5175 { 31, 73, 0.4015805401 },
5176 { 41, 92, 0.4192323938 },
5177 { 7, 15, 0.4366271598 },
5178 { 20, 41, 0.4538440015 },
5179 { 27, 53, 0.4711662643 },
5180 { 42, 79, 0.4886424026 },
5181 { 51, 92, 0.5061751436 },
5182 { 56, 97, 0.5235757641 },
5183 { 3, 5, 0.5404195003 },
5184 { 5, 8, 0.5585993153 },
5185 { 50, 77, 0.5759185996 },
5186 { 29, 43, 0.5933501462 },
5187 { 7, 10, 0.6107259644 },
5188 { 69, 95, 0.6281701124 },
5189 { 52, 69, 0.6458159195 },
5190 { 25, 32, 0.6632029927 },
5191 { 17, 21, 0.6805212247 },
5192 { 73, 87, 0.6981204504 },
5193 { 73, 84, 0.7154487784 },
5194 { 9, 10, 0.7328151018 },
5195 { 83, 89, 0.7505285818 },
5196 { 28, 29, 0.7678561033 },
5197 { 1, 1, 0.7853981634 },
5198 { 29, 28, 0.8029402235 },
5199 { 89, 83, 0.820267745 },
5200 { 10, 9, 0.837981225 },
5201 { 107, 93, 0.855284165 },
5202 { 87, 73, 0.8726758763 },
5203 { 121, 98, 0.8900374031 },
5204 { 32, 25, 0.9075933341 },
5205 { 69, 52, 0.9249804073 },
5206 { 128, 93, 0.9424647244 },
5207 { 10, 7, 0.9600703624 },
5208 { 43, 29, 0.9774461806 },
5209 { 77, 50, 0.9948777272 },
5210 { 8, 5, 1.012197011 },
5211 { 163, 98, 1.029475114 },
5212 { 168, 97, 1.047174539 },
5213 { 175, 97, 1.064668696 },
5214 { 126, 67, 1.082075603 },
5215 { 157, 80, 1.099534652 },
5216 { 203, 99, 1.117049384 },
5217 { 193, 90, 1.134452855 },
5218 { 146, 65, 1.151936673 },
5219 { 139, 59, 1.169382787 },
5220 { 99, 40, 1.186811703 },
5221 { 211, 81, 1.204257817 },
5222 { 272, 99, 1.221730164 },
5223 { 273, 94, 1.239188479 },
5224 { 277, 90, 1.25664606 },
5225 { 157, 48, 1.274088705 },
5226 { 279, 80, 1.291550147 },
5227 { 362, 97, 1.308990773 },
5228 { 373, 93, 1.326448578 },
5229 { 420, 97, 1.343823596 },
5230 { 207, 44, 1.361353157 },
5231 { 427, 83, 1.378810994 },
5232 { 414, 73, 1.396261926 },
5233 { 322, 51, 1.413716057 },
5234 { 185, 26, 1.431170275 },
5235 { 790, 97, 1.448623034 },
5236 { 333, 35, 1.466075711 },
5237 { 1063, 93, 1.483530284 },
5238 { 1330, 93, 1.500985147 },
5239 { 706, 37, 1.518436297 },
5240 { 315, 11, 1.535889876 },
5241 { 3953, 69, 1.553343002 },
5247 static const QList<rationalTangent> rationalTangents
5249 { 1, 10, qDegreesToRadians( 5.71059 ) },
5250 { 1, 5, qDegreesToRadians( 11.3099 ) },
5251 { 1, 4, qDegreesToRadians( 14.0362 ) },
5252 { 1, 4, qDegreesToRadians( 18.4349 ) },
5253 { 1, 2, qDegreesToRadians( 26.5651 ) },
5254 { 2, 3, qDegreesToRadians( 33.6901 ) },
5255 { 1, 1, qDegreesToRadians( 45.0 ) },
5256 { 3, 2, qDegreesToRadians( 56.3099 ) },
5257 { 2, 1, qDegreesToRadians( 63.4349 ) },
5258 { 3, 1, qDegreesToRadians( 71.5651 ) },
5259 { 4, 1, qDegreesToRadians( 75.9638 ) },
5260 { 10, 1, qDegreesToRadians( 84.2894 ) },
5263 const int quadrant {
static_cast<int>( angleRad / M_PI_2 ) };
5264 Q_ASSERT( quadrant >= 0 && quadrant <= 3 );
5276 angleRad -= M_PI / 2;
5286 angleRad -= M_PI + M_PI_2;
5308 for (
int idx = 0; idx < rationalTangents.count(); ++idx )
5310 const auto item = rationalTangents.at( idx );
5311 if (
qgsDoubleNear( item.angle, angleRad, 10E-3 ) || item.angle > angleRad )
5318 const rationalTangent bTan { rationalTangents.at( rTanIdx ) };
5319 angleRad = bTan.angle;
5320 const double k { bTan.q *height *width / std::cos( angleRad ) };
5321 const int hcfH { std::gcd( bTan.p * height, bTan.q * width ) };
5322 const int hcfW { std::gcd( bTan.q * height, bTan.p * width ) };
5323 const int W1 {
static_cast<int>( std::round( k / hcfW ) ) };
5324 const int H1 {
static_cast<int>( std::round( k / hcfH ) ) };
5337 angleRad += M_PI / 2;
5350 angleRad += M_PI + M_PI_2;
5361template <
typename Functor>
5364 sl->
setId( generateId() );
5372template <
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.
RenderUnit
Rendering size units.
@ 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.
@ RendererShouldUseSymbolLevels
If present, indicates that a QgsFeatureRenderer using the symbol should use symbol levels for best re...
@ MultiPolygon
MultiPolygon.
@ MultiLineString
MultiLineString.
SymbolCoordinateReference
Symbol coordinate reference modes.
@ Feature
Relative to feature/shape being rendered.
@ Viewport
Relative to the whole viewport/output device.
virtual bool readXml(const QDomElement &collectionElem, const QgsPropertiesDefinition &definitions)
Reads property collection state from an XML element.
virtual bool writeXml(QDomElement &collectionElem, const QgsPropertiesDefinition &definitions) const
Writes the current state of the property collection into an XML element.
Animated marker symbol layer class.
static QgsPaintEffectRegistry * paintEffectRegistry()
Returns the application's paint effect registry, used for managing paint effects.
static QgsSymbolLayerRegistry * symbolLayerRegistry()
Returns the application's symbol layer registry, used for managing symbol layers.
static QStringList svgPaths()
Returns the paths to svg directories.
HeadType
Possible head types.
ArrowType
Possible arrow types.
static QString typeString()
Returns the string identifier for QgsColorBrewerColorRamp.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Returns a new QgsColorBrewerColorRamp color ramp created using the properties encoded in a string map...
Abstract base class for color ramps.
virtual QColor color(double value) const =0
Returns the color corresponding to a specified value.
virtual double value(int index) const =0
Returns relative value between [0,1] of color at specified index.
virtual QVariantMap properties() const =0
Returns a string map containing all the color ramp's properties.
virtual QString type() const =0
Returns a string representing the color ramp type.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates the symbol layer.
static QString typeString()
Returns the string identifier for QgsCptCityColorRamp.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
bool hasFeature() const
Returns true if the context has a feature associated with it.
An expression node which takes it value from a feature's field.
Abstract base class for all nodes that can appear in an expression.
virtual QgsExpressionNode::NodeType nodeType() const =0
Gets the type of this node.
Class for parsing and evaluation of expressions (formerly called "search strings").
QString expression() const
Returns the original, unmodified expression string.
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
QString parserErrorString() const
Returns parser error.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
const QgsExpressionNode * rootNode() const
Returns the root node of the expression.
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
static double normalizedAngle(double angle) SIP_HOLDGIL
Ensures that an angle is in the range 0 <= angle < 2 pi.
static QgsPoint pointOnLineWithDistance(const QgsPoint &startPoint, const QgsPoint &directionPoint, double distance) SIP_HOLDGIL
Returns a point a specified distance toward a second point.
A geometry is the spatial representation of a feature.
QgsMultiPolygonXY asMultiPolygon() const
Returns the contents of the geometry as a multi-polygon.
QgsGeometry offsetCurve(double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit) const
Returns an offset line at a given distance and side from an input line.
QgsGeometry pointOnSurface() const
Returns a point guaranteed to lie on the surface of a geometry.
static QgsGeometry fromPolylineXY(const QgsPolylineXY &polyline)
Creates a new LineString geometry from a list of QgsPointXY points.
QgsPolygonXY asPolygon() const
Returns the contents of the geometry as a polygon.
Qgis::WkbType wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
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...
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 setX(double x) SIP_HOLDGIL
Sets the point's x-coordinate.
void setY(double y) SIP_HOLDGIL
Sets the point's y-coordinate.
static QString typeString()
Returns the string identifier for QgsPresetSchemeColorRamp.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Returns a new QgsPresetSchemeColorRamp color ramp created using the properties encoded in a string ma...
A grouped map of multiple QgsProperty objects, each referenced by a integer key value.
QgsProperty property(int key) const override
Returns a matching property from the collection, if one exists.
QSet< int > propertyKeys() const override
Returns a list of property keys contained within the collection.
A store for object properties.
bool isProjectColor() const
Returns true if the property is set to a linked project color.
bool isActive() const
Returns whether the property is currently active.
void setActive(bool active)
Sets whether the property is currently active.
The class is used as a container of context for various read/write operations on other objects.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
Contains information about the context of a rendering operation.
void setForceVectorOutput(bool force)
Sets whether rendering operations should use vector operations instead of any faster raster shortcuts...
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
void 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.
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 QPixmap symbolPreviewPixmap(const QgsSymbol *symbol, QSize size, int padding=0, QgsRenderContext *customContext=nullptr, bool selected=false, const QgsExpressionContext *expressionContext=nullptr, const QgsLegendPatchShape *shape=nullptr)
Returns a pixmap preview for a color ramp.
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 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 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 QIcon symbolPreviewIcon(const QgsSymbol *symbol, QSize size, int padding=0, QgsLegendPatchShape *shape=nullptr)
Returns an icon preview for a color ramp.
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 QIcon symbolLayerPreviewIcon(const QgsSymbolLayer *layer, Qgis::RenderUnit u, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::SymbolType parentSymbolType=Qgis::SymbolType::Hybrid, QgsMapLayer *mapLayer=nullptr)
Draws a symbol layer preview to an icon.
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 QMimeData * colorToMimeData(const QColor &color)
Creates mime data from a color.
static bool condenseFillAndOutline(QgsFillSymbolLayer *fill, QgsLineSymbolLayer *outline)
Attempts to condense a fill and outline layer, by moving the outline layer to the fill symbol's strok...
static QPointF decodePoint(const QString &string)
Decodes a QSizeF from a string.
static QPolygonF polylineSubstring(const QPolygonF &polyline, double startOffset, double endOffset)
Returns the substring of a polyline which starts at startOffset from the beginning of the line and en...
static QgsSymbolLayer * createLineLayerFromSld(QDomElement &element)
static bool needPointPatternFill(QDomElement &element)
static QString encodeSldRealVector(const QVector< qreal > &v)
static QString encodeCoordinateReference(Qgis::SymbolCoordinateReference coordinateReference)
Encodes a symbol coordinate reference mode to a string.
static QgsSymbolLayer * createFillLayerFromSld(QDomElement &element)
static bool needRasterImageFill(QDomElement &element)
Checks if element contains a graphic fill with a raster image of type PNG, JPEG or GIF.
static QDomElement createSvgParameterElement(QDomDocument &doc, const QString &name, const QString &value)
static QString encodeMarkerClipMode(Qgis::MarkerClipMode mode)
Encodes a marker clip mode to a string.
static QgsExpression * fieldOrExpressionToExpression(const QString &fieldOrExpression)
Returns a new valid expression instance for given field or expression string.
static QSizeF decodeSize(const QString &string)
Decodes a QSizeF from a string.
static QString encodeRealVector(const QVector< qreal > &v)
Property
Data definable properties.
virtual QgsSymbolLayer * clone() const =0
Shall be reimplemented by subclasses to create a deep copy of the instance.
virtual bool setSubSymbol(QgsSymbol *symbol)
Sets layer's subsymbol. takes ownership of the passed symbol.
void setId(const QString &id)
Set symbol layer identifier This id has to be unique in the whole project.
bool isLocked() const
Returns true if the symbol layer colors are locked and the layer will ignore any symbol-level color c...
void setPaintEffect(QgsPaintEffect *effect)
Sets the current paint effect for the layer.
void setRenderingPass(int renderingPass)
Specifies the rendering pass in which this symbol layer should be rendered.
virtual double estimateMaxBleed(const QgsRenderContext &context) const
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape when ...
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the layer.
void setEnabled(bool enabled)
Sets whether symbol layer is enabled and should be drawn.
virtual QVariantMap properties() const =0
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
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.
virtual QColor color() const
Returns the "representative" color of the symbol layer.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol layer property definitions.
void setLocked(bool locked)
Sets whether the layer's colors are locked.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
virtual bool hasDataDefinedProperties() const
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
void setOriginalGeometryType(Qgis::GeometryType type)
Sets the geometry type for the original feature geometry being rendered.
Abstract base class for all rendered symbols.
void setOutputUnit(Qgis::RenderUnit unit) const
Sets the units to use for sizes and widths within the symbol.
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol's property collection, used for data defined overrides.
QgsSymbolAnimationSettings & animationSettings()
Returns a reference to the symbol animation settings.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol property definitions.
Qgis::SymbolFlags flags() const
Returns flags for the symbol.
qreal opacity() const
Returns the opacity for the symbol.
void setMapUnitScale(const QgsMapUnitScale &scale) const
Sets the map unit scale for the symbol.
bool clipFeaturesToExtent() const
Returns whether features drawn by the symbol will be clipped to the render context's extent.
void setFlags(Qgis::SymbolFlags flags)
Sets flags for the symbol.
bool hasDataDefinedProperties() const
Returns whether the symbol utilizes any data defined properties.
QgsSymbolLayerList symbolLayers() const
Returns the list of symbol layers contained in the symbol.
void setOpacity(qreal opacity)
Sets the opacity for the symbol.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
QColor color() const
Returns the symbol's color.
Qgis::SymbolType type() const
Returns the symbol's type.
bool forceRHR() const
Returns true if polygon features drawn by the symbol will be reoriented to follow the standard right-...
void setClipFeaturesToExtent(bool clipFeaturesToExtent)
Sets whether features drawn by the symbol should be clipped to the render context's extent.
void setForceRHR(bool force)
Sets whether polygon features drawn by the symbol should be reoriented to follow the standard right-h...
static Q_INVOKABLE Qgis::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
static bool isNull(const QVariant &variant)
Returns true if the specified variant should be considered a NULL value.
static Qgis::WkbType flatType(Qgis::WkbType type) SIP_HOLDGIL
Returns the flat type for a WKB type.
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement.
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement.
QList< QPair< QColor, QString > > QgsNamedColorList
List of colors paired with a friendly display name identifying the color.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
CORE_EXPORT QgsMeshVertex centroid(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns the centroid of the face.
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.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QMap< QString, QString > QgsStringMap
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)
QMap< QString, QgsSymbol * > QgsSymbolMap
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)
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.