49 #include <QDomDocument>
51 #include <QDomElement>
59 #include <QRegularExpression>
61 #define POINTS_TO_MM 2.83464567
65 return QStringLiteral(
"%1,%2,%3,%4" ).arg( color.red() ).arg( color.green() ).arg( color.blue() ).arg( color.alpha() );
70 const QStringList lst =
str.split(
',' );
71 if ( lst.count() < 3 )
75 int red, green, blue, alpha;
77 green = lst[1].toInt();
78 blue = lst[2].toInt();
80 if ( lst.count() > 3 )
82 alpha = lst[3].toInt();
84 return QColor( red, green, blue, alpha );
89 return QString::number( alpha / 255.0,
'g', 2 );
95 double alpha =
str.toDouble( &ok );
96 if ( !ok || alpha > 1 )
107 case QFont::StyleNormal:
108 return QStringLiteral(
"normal" );
109 case QFont::StyleItalic:
110 return QStringLiteral(
"italic" );
111 case QFont::StyleOblique:
112 return QStringLiteral(
"oblique" );
120 if (
str == QLatin1String(
"normal" ) )
return QFont::StyleNormal;
121 if (
str == QLatin1String(
"italic" ) )
return QFont::StyleItalic;
122 if (
str == QLatin1String(
"oblique" ) )
return QFont::StyleOblique;
123 return QFont::StyleNormal;
128 if ( weight == 50 )
return QStringLiteral(
"normal" );
129 if ( weight == 75 )
return QStringLiteral(
"bold" );
133 if ( weight < 0 )
return QStringLiteral(
"100" );
134 if ( weight > 99 )
return QStringLiteral(
"900" );
135 return QString::number( weight * 800 / 99 + 100 );
141 const int weight =
str.toInt( &ok );
143 return static_cast< int >( QFont::Normal );
147 if ( weight > 900 )
return 99;
148 if ( weight < 100 )
return 0;
149 return ( weight - 100 ) * 99 / 800;
157 return QStringLiteral(
"no" );
159 return QStringLiteral(
"solid" );
161 return QStringLiteral(
"dash" );
163 return QStringLiteral(
"dot" );
164 case Qt::DashDotLine:
165 return QStringLiteral(
"dash dot" );
166 case Qt::DashDotDotLine:
167 return QStringLiteral(
"dash dot dot" );
169 return QStringLiteral(
"???" );
175 if (
str == QLatin1String(
"no" ) )
return Qt::NoPen;
176 if (
str == QLatin1String(
"solid" ) )
return Qt::SolidLine;
177 if (
str == QLatin1String(
"dash" ) )
return Qt::DashLine;
178 if (
str == QLatin1String(
"dot" ) )
return Qt::DotLine;
179 if (
str == QLatin1String(
"dash dot" ) )
return Qt::DashDotLine;
180 if (
str == QLatin1String(
"dash dot dot" ) )
return Qt::DashDotDotLine;
181 return Qt::SolidLine;
189 return QStringLiteral(
"bevel" );
191 return QStringLiteral(
"miter" );
193 return QStringLiteral(
"round" );
195 return QStringLiteral(
"???" );
201 const QString cleaned =
str.toLower().trimmed();
202 if ( cleaned == QLatin1String(
"bevel" ) )
203 return Qt::BevelJoin;
204 if ( cleaned == QLatin1String(
"miter" ) )
205 return Qt::MiterJoin;
206 if ( cleaned == QLatin1String(
"round" ) )
207 return Qt::RoundJoin;
208 return Qt::BevelJoin;
216 return QStringLiteral(
"bevel" );
218 return QStringLiteral(
"mitre" );
220 return QStringLiteral(
"round" );
228 if (
str == QLatin1String(
"bevel" ) )
return Qt::BevelJoin;
229 if (
str == QLatin1String(
"mitre" ) )
return Qt::MiterJoin;
230 if (
str == QLatin1String(
"round" ) )
return Qt::RoundJoin;
231 return Qt::BevelJoin;
239 return QStringLiteral(
"square" );
241 return QStringLiteral(
"flat" );
243 return QStringLiteral(
"round" );
245 return QStringLiteral(
"???" );
251 if (
str == QLatin1String(
"square" ) )
return Qt::SquareCap;
252 if (
str == QLatin1String(
"flat" ) )
return Qt::FlatCap;
253 if (
str == QLatin1String(
"round" ) )
return Qt::RoundCap;
254 return Qt::SquareCap;
262 return QStringLiteral(
"square" );
264 return QStringLiteral(
"butt" );
266 return QStringLiteral(
"round" );
274 if (
str == QLatin1String(
"square" ) )
return Qt::SquareCap;
275 if (
str == QLatin1String(
"butt" ) )
return Qt::FlatCap;
276 if (
str == QLatin1String(
"round" ) )
return Qt::RoundCap;
277 return Qt::SquareCap;
284 case Qt::SolidPattern :
285 return QStringLiteral(
"solid" );
286 case Qt::HorPattern :
287 return QStringLiteral(
"horizontal" );
288 case Qt::VerPattern :
289 return QStringLiteral(
"vertical" );
290 case Qt::CrossPattern :
291 return QStringLiteral(
"cross" );
292 case Qt::BDiagPattern :
293 return QStringLiteral(
"b_diagonal" );
294 case Qt::FDiagPattern :
295 return QStringLiteral(
"f_diagonal" );
296 case Qt::DiagCrossPattern :
297 return QStringLiteral(
"diagonal_x" );
298 case Qt::Dense1Pattern :
299 return QStringLiteral(
"dense1" );
300 case Qt::Dense2Pattern :
301 return QStringLiteral(
"dense2" );
302 case Qt::Dense3Pattern :
303 return QStringLiteral(
"dense3" );
304 case Qt::Dense4Pattern :
305 return QStringLiteral(
"dense4" );
306 case Qt::Dense5Pattern :
307 return QStringLiteral(
"dense5" );
308 case Qt::Dense6Pattern :
309 return QStringLiteral(
"dense6" );
310 case Qt::Dense7Pattern :
311 return QStringLiteral(
"dense7" );
313 return QStringLiteral(
"no" );
315 return QStringLiteral(
"???" );
321 if (
str == QLatin1String(
"solid" ) )
return Qt::SolidPattern;
322 if (
str == QLatin1String(
"horizontal" ) )
return Qt::HorPattern;
323 if (
str == QLatin1String(
"vertical" ) )
return Qt::VerPattern;
324 if (
str == QLatin1String(
"cross" ) )
return Qt::CrossPattern;
325 if (
str == QLatin1String(
"b_diagonal" ) )
return Qt::BDiagPattern;
326 if (
str == QLatin1String(
"f_diagonal" ) )
return Qt::FDiagPattern;
327 if (
str == QLatin1String(
"diagonal_x" ) )
return Qt::DiagCrossPattern;
328 if (
str == QLatin1String(
"dense1" ) )
return Qt::Dense1Pattern;
329 if (
str == QLatin1String(
"dense2" ) )
return Qt::Dense2Pattern;
330 if (
str == QLatin1String(
"dense3" ) )
return Qt::Dense3Pattern;
331 if (
str == QLatin1String(
"dense4" ) )
return Qt::Dense4Pattern;
332 if (
str == QLatin1String(
"dense5" ) )
return Qt::Dense5Pattern;
333 if (
str == QLatin1String(
"dense6" ) )
return Qt::Dense6Pattern;
334 if (
str == QLatin1String(
"dense7" ) )
return Qt::Dense7Pattern;
335 if (
str == QLatin1String(
"no" ) )
return Qt::NoBrush;
336 return Qt::SolidPattern;
343 case Qt::CrossPattern:
344 return QStringLiteral(
"cross" );
345 case Qt::DiagCrossPattern:
346 return QStringLiteral(
"x" );
353 return QStringLiteral(
"horline" );
355 return QStringLiteral(
"line" );
356 case Qt::BDiagPattern:
357 return QStringLiteral(
"slash" );
358 case Qt::FDiagPattern:
359 return QStringLiteral(
"backslash" );
362 case Qt::Dense1Pattern:
363 case Qt::Dense2Pattern:
364 case Qt::Dense3Pattern:
365 case Qt::Dense4Pattern:
366 case Qt::Dense5Pattern:
367 case Qt::Dense6Pattern:
368 case Qt::Dense7Pattern:
378 if (
str == QLatin1String(
"horline" ) )
return Qt::HorPattern;
379 if (
str == QLatin1String(
"line" ) )
return Qt::VerPattern;
380 if (
str == QLatin1String(
"cross" ) )
return Qt::CrossPattern;
381 if (
str == QLatin1String(
"slash" ) )
return Qt::BDiagPattern;
382 if (
str == QLatin1String(
"backshash" ) )
return Qt::FDiagPattern;
383 if (
str == QLatin1String(
"x" ) )
return Qt::DiagCrossPattern;
385 if (
str.startsWith( QLatin1String(
"brush://" ) ) )
393 const QString compareString =
string.trimmed();
397 if ( compareString.compare( QLatin1String(
"feature" ), Qt::CaseInsensitive ) == 0 )
399 else if ( compareString.compare( QLatin1String(
"viewport" ), Qt::CaseInsensitive ) == 0 )
409 switch ( coordinateReference )
412 return QStringLiteral(
"feature" );
414 return QStringLiteral(
"viewport" );
425 const QString s = value.toString().toLower().trimmed();
426 if ( s == QLatin1String(
"single" ) )
428 else if ( s == QLatin1String(
"reversed" ) )
430 else if ( s == QLatin1String(
"double" ) )
432 else if ( value.toInt() == 1 )
434 else if ( value.toInt() == 2 )
436 else if ( value.toInt( &intOk ) == 0 && intOk )
450 const QString s = value.toString().toLower().trimmed();
451 if ( s == QLatin1String(
"plain" ) )
453 else if ( s == QLatin1String(
"lefthalf" ) )
455 else if ( s == QLatin1String(
"righthalf" ) )
457 else if ( value.toInt() == 1 )
459 else if ( value.toInt() == 2 )
461 else if ( value.toInt( &intOk ) == 0 && intOk )
471 const QString compareString =
string.trimmed();
475 if ( compareString.compare( QLatin1String(
"no" ), Qt::CaseInsensitive ) == 0 )
477 else if ( compareString.compare( QLatin1String(
"shape" ), Qt::CaseInsensitive ) == 0 )
479 else if ( compareString.compare( QLatin1String(
"centroid_within" ), Qt::CaseInsensitive ) == 0 )
481 else if ( compareString.compare( QLatin1String(
"completely_within" ), Qt::CaseInsensitive ) == 0 )
494 return QStringLiteral(
"no" );
496 return QStringLiteral(
"shape" );
498 return QStringLiteral(
"centroid_within" );
500 return QStringLiteral(
"completely_within" );
507 const QString compareString =
string.trimmed();
511 if ( compareString.compare( QLatin1String(
"no" ), Qt::CaseInsensitive ) == 0 )
513 else if ( compareString.compare( QLatin1String(
"during_render" ), Qt::CaseInsensitive ) == 0 )
515 else if ( compareString.compare( QLatin1String(
"before_render" ), Qt::CaseInsensitive ) == 0 )
528 return QStringLiteral(
"no" );
530 return QStringLiteral(
"during_render" );
532 return QStringLiteral(
"before_render" );
544 QStringList lst =
str.split(
',' );
545 if ( lst.count() != 2 )
546 return QPointF( 0, 0 );
547 return QPointF( lst[0].toDouble(), lst[1].toDouble() );
555 if ( value.isNull() )
558 if ( value.type() == QVariant::List )
560 const QVariantList list = value.toList();
561 if ( list.size() != 2 )
565 bool convertOk =
false;
566 const double x = list.at( 0 ).toDouble( &convertOk );
569 const double y = list.at( 1 ).toDouble( &convertOk );
574 return QPointF( x, y );
582 const QStringList list = value.toString().trimmed().split(
',' );
583 if ( list.count() != 2 )
585 bool convertOk =
false;
586 const double x = list.at( 0 ).toDouble( &convertOk );
589 const double y = list.at( 1 ).toDouble( &convertOk );
594 return QPointF( x, y );
608 QStringList lst =
string.split(
',' );
609 if ( lst.count() != 2 )
610 return QSizeF( 0, 0 );
611 return QSizeF( lst[0].toDouble(), lst[1].toDouble() );
619 if ( value.isNull() )
622 if ( value.type() == QVariant::List )
624 const QVariantList list = value.toList();
625 if ( list.size() != 2 )
629 bool convertOk =
false;
630 const double x = list.at( 0 ).toDouble( &convertOk );
633 const double y = list.at( 1 ).toDouble( &convertOk );
638 return QSizeF( x, y );
646 const QStringList list = value.toString().trimmed().split(
',' );
647 if ( list.count() != 2 )
649 bool convertOk =
false;
650 const double x = list.at( 0 ).toDouble( &convertOk );
653 const double y = list.at( 1 ).toDouble( &convertOk );
658 return QSizeF( x, y );
679 if (
str.startsWith( QLatin1String(
"3x:" ) ) )
682 const QString chopped =
str.mid( 3 );
683 lst = chopped.split(
',' );
687 lst =
str.split(
',' );
689 if ( lst.count() < 2 )
692 double minScale = lst[0].toDouble();
694 minScale = minScale != 0 ? 1.0 / minScale : 0;
695 double maxScale = lst[1].toDouble();
697 maxScale = maxScale != 0 ? 1.0 / maxScale : 0;
699 if ( lst.count() < 6 )
719 *scaleFactor = 0.001;
720 return QStringLiteral(
"http://www.opengeospatial.org/se/units/metre" );
727 *scaleFactor = 1 / 0.28;
736 if (
str == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
739 *scaleFactor = 1000.0;
742 else if (
str == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
745 *scaleFactor = 304.8;
748 else if (
str == QLatin1String(
"http://www.opengeospatial.org/se/units/pixel" ) )
758 *scaleFactor = 1 / 0.00028;
764 QString vectorString;
765 QVector<qreal>::const_iterator it = v.constBegin();
766 for ( ; it != v.constEnd(); ++it )
768 if ( it != v.constBegin() )
770 vectorString.append(
';' );
772 vectorString.append( QString::number( *it ) );
779 QVector<qreal> resultVector;
781 const QStringList realList = s.split(
';' );
782 QStringList::const_iterator it = realList.constBegin();
783 for ( ; it != realList.constEnd(); ++it )
785 resultVector.append( it->toDouble() );
793 QString vectorString;
794 QVector<qreal>::const_iterator it = v.constBegin();
795 for ( ; it != v.constEnd(); ++it )
797 if ( it != v.constBegin() )
799 vectorString.append(
' ' );
801 vectorString.append( QString::number( *it ) );
808 QVector<qreal> resultVector;
810 const QStringList realList = s.split(
' ' );
811 QStringList::const_iterator it = realList.constBegin();
812 for ( ; it != realList.constEnd(); ++it )
814 resultVector.append( it->toDouble() );
822 QString encodedValue;
824 switch ( scaleMethod )
827 encodedValue = QStringLiteral(
"diameter" );
830 encodedValue = QStringLiteral(
"area" );
840 if (
str == QLatin1String(
"diameter" ) )
854 if ( s.compare( QLatin1String(
"Lighten" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Lighten;
855 if ( s.compare( QLatin1String(
"Screen" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Screen;
856 if ( s.compare( QLatin1String(
"Dodge" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorDodge;
857 if ( s.compare( QLatin1String(
"Addition" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Plus;
858 if ( s.compare( QLatin1String(
"Darken" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Darken;
859 if ( s.compare( QLatin1String(
"Multiply" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Multiply;
860 if ( s.compare( QLatin1String(
"Burn" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorBurn;
861 if ( s.compare( QLatin1String(
"Overlay" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Overlay;
862 if ( s.compare( QLatin1String(
"SoftLight" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_SoftLight;
863 if ( s.compare( QLatin1String(
"HardLight" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_HardLight;
864 if ( s.compare( QLatin1String(
"Difference" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Difference;
865 if ( s.compare( QLatin1String(
"Subtract" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Exclusion;
866 return QPainter::CompositionMode_SourceOver;
871 return QIcon(
symbolPreviewPixmap( symbol, size, padding,
nullptr,
false,
nullptr, shape ) );
877 QPixmap pixmap( size );
878 pixmap.fill( Qt::transparent );
880 painter.begin( &pixmap );
885 painter.setRenderHint( QPainter::Antialiasing );
886 painter.setRenderHint( QPainter::SmoothPixmapTransform );
896 size.setWidth( size.rwidth() - ( padding * 2 ) );
897 size.setHeight( size.rheight() - ( padding * 2 ) );
898 painter.translate( padding, padding );
908 std::unique_ptr<QgsSymbol> symbol_noDD( symbol->
clone( ) );
910 for (
const auto &layer : layers )
912 for (
int i = 0; i < layer->dataDefinedProperties().count(); ++i )
914 QgsProperty &prop = layer->dataDefinedProperties().property( i );
920 symbol_noDD->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape );
924 std::unique_ptr<QgsSymbol> symbolClone( symbol->
clone( ) );
925 symbolClone->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape );
939 maxBleed = layerMaxBleed > maxBleed ? layerMaxBleed : maxBleed;
949 painter.begin( &picture );
950 painter.setRenderHint( QPainter::Antialiasing );
958 QgsSymbolRenderContext symbolContext( renderContext, units, 1.0,
false, Qgis::SymbolRenderHints(),
nullptr );
960 switch ( parentSymbolType )
975 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
976 layerClone->drawPreviewIcon( symbolContext, size );
983 QPixmap pixmap( size );
984 pixmap.fill( Qt::transparent );
986 painter.begin( &pixmap );
987 painter.setRenderHint( QPainter::Antialiasing );
998 switch ( parentSymbolType )
1013 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
1014 layerClone->drawPreviewIcon( symbolContext, size );
1016 return QIcon( pixmap );
1026 QPixmap pixmap( size );
1027 pixmap.fill( Qt::transparent );
1030 painter.begin( &pixmap );
1033 if ( drawTransparentBackground )
1034 drawStippledBackground( &painter, QRect( padding, padding, size.width() - padding * 2, size.height() - padding * 2 ) );
1038 switch ( direction )
1040 case Qt::Horizontal:
1042 for (
int i = 0; i < size.width(); i++ )
1044 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.width() ) );
1045 painter.setPen( pen );
1046 const int x = flipDirection ? size.width() - i - 1 : i;
1047 painter.drawLine( x, 0 + padding, x, size.height() - 1 - padding );
1054 for (
int i = 0; i < size.height(); i++ )
1056 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.height() ) );
1057 painter.setPen( pen );
1058 const int y = flipDirection ? size.height() - i - 1 : i;
1059 painter.drawLine( 0 + padding, y, size.width() - 1 - padding, y );
1072 uchar pixDataRGB[] = { 255, 255, 255, 255,
1077 const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
1079 const int width = ( rect.width() < rect.height() ) ?
1080 rect.width() / 2.5 : rect.height() / 2.5;
1081 const QPixmap pix = QPixmap::fromImage( img.scaled( width, width ) );
1084 brush.setTexture( pix );
1085 painter->fillRect( rect, brush );
1090 const qreal s = ( markerSize - 1 ) / 2.0;
1095 p.setPen( QColor( 50, 100, 120, 200 ) );
1096 p.setBrush( QColor( 200, 200, 210, 120 ) );
1097 p.drawEllipse( x - s, y - s, s * 2, s * 2 );
1100 p.setPen( QColor( 255, 0, 0 ) );
1101 p.drawLine( x - s, y + s, x + s, y - s );
1102 p.drawLine( x - s, y - s, x + s, y + s );
1109 #include <QPolygonF>
1114 static QPolygonF makeOffsetGeometry(
const QgsPolylineXY &polyline )
1116 int i, pointCount = polyline.count();
1118 QPolygonF resultLine;
1119 resultLine.resize( pointCount );
1123 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1124 resultLine[i] = QPointF( tempPtr->
x(), tempPtr->
y() );
1128 static QList<QPolygonF> makeOffsetGeometry(
const QgsPolygonXY &polygon )
1130 QList<QPolygonF> resultGeom;
1131 resultGeom.reserve( polygon.size() );
1132 for (
int ring = 0; ring < polygon.size(); ++ring )
1133 resultGeom.append( makeOffsetGeometry( polygon[ ring ] ) );
1139 QList<QPolygonF> resultLine;
1141 if ( polyline.count() < 2 )
1143 resultLine.append( polyline );
1147 unsigned int i, pointCount = polyline.count();
1150 QPointF *tempPtr = polyline.data();
1151 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1152 tempPolyline[i] =
QgsPointXY( tempPtr->rx(), tempPtr->ry() );
1155 if ( !tempGeometry.
isNull() )
1157 const int quadSegments = 0;
1158 const double miterLimit = 2.0;
1161 offsetGeom = tempGeometry.
buffer( -dist, quadSegments, Qgis::EndCapStyle::Flat,
1162 Qgis::JoinStyle::Miter, miterLimit );
1164 offsetGeom = tempGeometry.
offsetCurve( dist, quadSegments, Qgis::JoinStyle::Miter, miterLimit );
1166 if ( !offsetGeom.
isNull() )
1168 tempGeometry = offsetGeom;
1173 resultLine.append( makeOffsetGeometry( line ) );
1178 resultLine.append( makeOffsetGeometry( tempGeometry.
asPolygon() ) );
1184 resultLine.reserve( tempMPolyline.count() );
1185 for (
int part = 0; part < tempMPolyline.count(); ++part )
1187 resultLine.append( makeOffsetGeometry( tempMPolyline[ part ] ) );
1194 resultLine.reserve( tempMPolygon.count() );
1195 for (
int part = 0; part < tempMPolygon.count(); ++part )
1197 resultLine.append( makeOffsetGeometry( tempMPolygon[ part ] ) );
1205 resultLine.append( polyline );
1215 QDomNode layerNode = element.firstChild();
1217 while ( !layerNode.isNull() )
1219 QDomElement e = layerNode.toElement();
1220 if ( !e.isNull() && e.tagName() != QLatin1String(
"data_defined_properties" ) )
1222 if ( e.tagName() != QLatin1String(
"layer" ) )
1231 const QDomElement s = e.firstChildElement( QStringLiteral(
"symbol" ) );
1234 std::unique_ptr< QgsSymbol > subSymbol(
loadSymbol( s, context ) );
1241 layers.append( layer );
1243 for (
int i = 0; i < subSymbol->symbolLayerCount(); ++i )
1245 layers.append( subSymbol->symbolLayer( i )->clone() );
1250 const bool res = layer->setSubSymbol( subSymbol.release() );
1253 QgsDebugMsg( QStringLiteral(
"symbol layer refused subsymbol: " ) + s.attribute(
"name" ) );
1255 layers.append( layer );
1260 layers.append( layer );
1265 layerNode = layerNode.nextSibling();
1268 if ( layers.isEmpty() )
1270 QgsDebugMsg( QStringLiteral(
"no layers for symbol" ) );
1274 const QString symbolType = element.attribute( QStringLiteral(
"type" ) );
1277 if ( symbolType == QLatin1String(
"line" ) )
1279 else if ( symbolType == QLatin1String(
"fill" ) )
1281 else if ( symbolType == QLatin1String(
"marker" ) )
1285 QgsDebugMsg(
"unknown symbol type " + symbolType );
1289 if ( element.hasAttribute( QStringLiteral(
"outputUnit" ) ) )
1293 if ( element.hasAttribute( ( QStringLiteral(
"mapUnitScale" ) ) ) )
1296 const double oldMin = element.attribute( QStringLiteral(
"mapUnitMinScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1297 mapUnitScale.
minScale = oldMin != 0 ? 1.0 / oldMin : 0;
1298 const double oldMax = element.attribute( QStringLiteral(
"mapUnitMaxScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1299 mapUnitScale.
maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
1302 symbol->
setOpacity( element.attribute( QStringLiteral(
"alpha" ), QStringLiteral(
"1.0" ) ).toDouble() );
1303 symbol->
setClipFeaturesToExtent( element.attribute( QStringLiteral(
"clip_to_extent" ), QStringLiteral(
"1" ) ).toInt() );
1304 symbol->
setForceRHR( element.attribute( QStringLiteral(
"force_rhr" ), QStringLiteral(
"0" ) ).toInt() );
1305 Qgis::SymbolFlags flags;
1306 if ( element.attribute( QStringLiteral(
"renderer_should_use_levels" ), QStringLiteral(
"0" ) ).toInt() )
1310 const QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1311 if ( !ddProps.isNull() )
1321 const QString layerClass = element.attribute( QStringLiteral(
"class" ) );
1322 const bool locked = element.attribute( QStringLiteral(
"locked" ) ).toInt();
1323 const bool enabled = element.attribute( QStringLiteral(
"enabled" ), QStringLiteral(
"1" ) ).toInt();
1324 const int pass = element.attribute( QStringLiteral(
"pass" ) ).toInt();
1343 const QDomElement effectElem = element.firstChildElement( QStringLiteral(
"effect" ) );
1344 if ( !effectElem.isNull() )
1352 const QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1353 if ( !ddProps.isNull() )
1360 const QSet< int > oldKeys = prevProperties.
propertyKeys();
1361 for (
int key : oldKeys )
1382 return QStringLiteral(
"line" );
1384 return QStringLiteral(
"marker" );
1386 return QStringLiteral(
"fill" );
1395 QDomElement symEl = doc.createElement( QStringLiteral(
"symbol" ) );
1396 symEl.setAttribute( QStringLiteral(
"type" ), _nameForSymbolType( symbol->
type() ) );
1397 symEl.setAttribute( QStringLiteral(
"name" ), name );
1398 symEl.setAttribute( QStringLiteral(
"alpha" ), QString::number( symbol->
opacity() ) );
1399 symEl.setAttribute( QStringLiteral(
"clip_to_extent" ), symbol->
clipFeaturesToExtent() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1400 symEl.setAttribute( QStringLiteral(
"force_rhr" ), symbol->
forceRHR() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1402 symEl.setAttribute( QStringLiteral(
"renderer_should_use_levels" ), QStringLiteral(
"1" ) );
1406 QDomElement ddProps = doc.createElement( QStringLiteral(
"data_defined_properties" ) );
1408 symEl.appendChild( ddProps );
1414 QDomElement layerEl = doc.createElement( QStringLiteral(
"layer" ) );
1415 layerEl.setAttribute( QStringLiteral(
"class" ), layer->
layerType() );
1416 layerEl.setAttribute( QStringLiteral(
"enabled" ), layer->
enabled() );
1417 layerEl.setAttribute( QStringLiteral(
"locked" ), layer->
isLocked() );
1418 layerEl.setAttribute( QStringLiteral(
"pass" ), layer->
renderingPass() );
1430 QDomElement ddProps = doc.createElement( QStringLiteral(
"data_defined_properties" ) );
1432 layerEl.appendChild( ddProps );
1436 const QString subname = QStringLiteral(
"@%1@%2" ).arg( name ).arg( i );
1437 const QDomElement subEl =
saveSymbol( subname, subSymbol, doc, context );
1438 layerEl.appendChild( subEl );
1440 symEl.appendChild( layerEl );
1448 QDomDocument doc( QStringLiteral(
"qgis-symbol-definition" ) );
1451 QTextStream stream( &props );
1452 symbolElem.save( stream, -1 );
1458 QList<QgsSymbolLayer *> &layers )
1462 if ( element.isNull() )
1467 const QString symbolizerName = element.localName();
1469 if ( symbolizerName == QLatin1String(
"PointSymbolizer" ) )
1472 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1473 if ( graphicElem.isNull() )
1475 QgsDebugMsg( QStringLiteral(
"Graphic element not found in PointSymbolizer" ) );
1511 if ( symbolizerName == QLatin1String(
"LineSymbolizer" ) )
1514 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1515 if ( strokeElem.isNull() )
1517 QgsDebugMsg( QStringLiteral(
"Stroke element not found in LineSymbolizer" ) );
1547 if ( symbolizerName == QLatin1String(
"PolygonSymbolizer" ) )
1550 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1551 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1552 if ( fillElem.isNull() && strokeElem.isNull() )
1554 QgsDebugMsg( QStringLiteral(
"neither Fill nor Stroke element not found in PolygonSymbolizer" ) );
1572 if ( l->
layerType() == QLatin1String(
"SimpleFill" ) || l->
layerType() == QLatin1String(
"SVGFill" ) )
1608 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1609 if ( fillElem.isNull() )
1611 QgsDebugMsg( QStringLiteral(
"Fill element not found" ) );
1631 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1632 if ( strokeElem.isNull() )
1634 QgsDebugMsg( QStringLiteral(
"Stroke element not found" ) );
1650 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1651 if ( graphicElem.isNull() )
1653 QgsDebugMsg( QStringLiteral(
"Graphic element not found" ) );
1673 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1674 if ( graphicElem.isNull() )
1677 const QDomElement externalGraphicElem = graphicElem.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
1678 if ( externalGraphicElem.isNull() )
1682 const QDomElement formatElem = externalGraphicElem.firstChildElement( QStringLiteral(
"Format" ) );
1683 if ( formatElem.isNull() )
1686 const QString format = formatElem.firstChild().nodeValue();
1687 if ( format != QLatin1String(
"image/svg+xml" ) )
1689 QgsDebugMsg(
"unsupported External Graphic format found: " + format );
1694 const QDomElement onlineResourceElem = externalGraphicElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1695 const QDomElement inlineContentElem = externalGraphicElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1696 if ( !onlineResourceElem.isNull() )
1701 else if ( !inlineContentElem.isNull() )
1714 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1715 if ( graphicElem.isNull() )
1718 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1719 if ( markElem.isNull() )
1722 const QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
1723 return !wellKnownNameElem.isNull();
1729 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1730 if ( graphicElem.isNull() )
1733 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1734 if ( markElem.isNull() )
1738 const QDomElement formatElem = markElem.firstChildElement( QStringLiteral(
"Format" ) );
1739 if ( formatElem.isNull() )
1742 const QString format = formatElem.firstChild().nodeValue();
1743 if ( format != QLatin1String(
"ttf" ) )
1745 QgsDebugMsg(
"unsupported Graphic Mark format found: " + format );
1750 const QDomElement onlineResourceElem = markElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1751 const QDomElement inlineContentElem = markElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1752 if ( !onlineResourceElem.isNull() )
1755 const QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
1756 if ( !markIndexElem.isNull() )
1759 else if ( !inlineContentElem.isNull() )
1774 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1775 if ( graphicElem.isNull() )
1779 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
1781 if ( it.key() == QLatin1String(
"widthHeightFactor" ) )
1792 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1793 if ( strokeElem.isNull() )
1796 QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral(
"GraphicStroke" ) );
1797 if ( graphicStrokeElem.isNull() )
1805 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1806 if ( fillElem.isNull() )
1809 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1810 if ( graphicFillElem.isNull() )
1813 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1814 if ( graphicElem.isNull() )
1820 QColor fillColor, strokeColor;
1821 double size, strokeWidth;
1822 Qt::PenStyle strokeStyle;
1823 if ( !
wellKnownMarkerFromSld( graphicElem, name, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
1826 if ( name != QLatin1String(
"horline" ) )
1834 const double angle = angleFunc.toDouble( &ok );
1846 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1847 if ( fillElem.isNull() )
1850 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1851 if ( graphicFillElem.isNull() )
1871 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1872 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1876 bool validFill =
false, validStroke =
false;
1881 Qt::BrushStyle fillStyle;
1883 if (
fillFromSld( fillElem, fillStyle, fillColor ) )
1889 Qt::PenStyle strokeStyle;
1890 double strokeWidth = 1.0, dashOffset = 0.0;
1891 QVector<qreal> customDashPattern;
1893 if (
lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth,
1894 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
1897 if ( validFill || validStroke )
1900 map[QStringLiteral(
"name" )] = QStringLiteral(
"square" );
1901 map[QStringLiteral(
"color" )] =
encodeColor( validFill ? fillColor : Qt::transparent );
1902 map[QStringLiteral(
"color_border" )] =
encodeColor( validStroke ? strokeColor : Qt::transparent );
1903 map[QStringLiteral(
"size" )] = QString::number( 6 );
1904 map[QStringLiteral(
"angle" )] = QString::number( 0 );
1905 map[QStringLiteral(
"offset" )] =
encodePoint( QPointF( 0, 0 ) );
1912 bool validFill =
false, validStroke =
false;
1915 QString name, format;
1917 QColor fillColor, strokeColor;
1918 double strokeWidth = 1.0, size = 0.0,
angle = 0.0;
1922 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1923 if ( !graphicFillElem.isNull() )
1926 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1927 if ( !graphicElem.isNull() )
1933 const QDomElement graphicChildElem = graphicElem.firstChildElement();
1934 while ( !graphicChildElem.isNull() )
1936 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
1939 const QDomElement wellKnownNameElem = graphicChildElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
1940 if ( !wellKnownNameElem.isNull() )
1942 name = wellKnownNameElem.firstChild().nodeValue();
1948 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) || graphicChildElem.localName() == QLatin1String(
"Mark" ) )
1951 const QDomElement formatElem = graphicChildElem.firstChildElement( QStringLiteral(
"Format" ) );
1952 if ( formatElem.isNull() )
1955 format = formatElem.firstChild().nodeValue();
1959 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) && format != QLatin1String(
"image/svg+xml" ) )
1964 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format != QLatin1String(
"ttf" ) )
1968 const QDomElement onlineResourceElem = graphicChildElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1969 const QDomElement inlineContentElem = graphicChildElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1971 if ( !onlineResourceElem.isNull() )
1973 name = onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) );
1975 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format == QLatin1String(
"ttf" ) )
1978 if ( name.startsWith( QLatin1String(
"ttf://" ) ) )
1979 name = name.mid( 6 );
1982 const QDomElement markIndexElem = graphicChildElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
1983 if ( markIndexElem.isNull() )
1987 const int v = markIndexElem.firstChild().nodeValue().toInt( &ok );
1998 else if ( !inlineContentElem.isNull() )
2008 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2010 name = QStringLiteral(
"square" );
2017 if ( found && graphicChildElem.localName() == QLatin1String(
"Mark" ) )
2024 Qt::BrushStyle markFillStyle;
2026 QDomElement markFillElem = graphicChildElem.firstChildElement( QStringLiteral(
"Fill" ) );
2027 if (
fillFromSld( markFillElem, markFillStyle, fillColor ) )
2032 Qt::PenStyle strokeStyle;
2033 double strokeWidth = 1.0, dashOffset = 0.0;
2034 QVector<qreal> customDashPattern;
2036 QDomElement markStrokeElem = graphicChildElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2037 if (
lineFromSld( markStrokeElem, strokeStyle, strokeColor, strokeWidth,
2038 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
2045 const QDomElement opacityElem = graphicElem.firstChildElement( QStringLiteral(
"Opacity" ) );
2046 if ( !opacityElem.isNull() )
2047 fillColor.setAlpha(
decodeSldAlpha( opacityElem.firstChild().nodeValue() ) );
2049 const QDomElement sizeElem = graphicElem.firstChildElement( QStringLiteral(
"Size" ) );
2050 if ( !sizeElem.isNull() )
2053 const double v = sizeElem.firstChild().nodeValue().toDouble( &ok );
2062 const double v = angleFunc.toDouble( &ok );
2072 if ( validFill || validStroke )
2074 if ( format == QLatin1String(
"image/svg+xml" ) )
2077 map[QStringLiteral(
"name" )] = name;
2078 map[QStringLiteral(
"fill" )] = fillColor.name();
2079 map[QStringLiteral(
"outline" )] = strokeColor.name();
2080 map[QStringLiteral(
"outline-width" )] = QString::number( strokeWidth );
2082 map[QStringLiteral(
"size" )] = QString::number( size );
2084 map[QStringLiteral(
"angle" )] = QString::number(
angle );
2085 if ( !offset.isNull() )
2086 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
2089 else if ( format == QLatin1String(
"ttf" ) )
2092 map[QStringLiteral(
"font" )] = name;
2093 map[QStringLiteral(
"chr" )] = markIndex;
2094 map[QStringLiteral(
"color" )] =
encodeColor( validFill ? fillColor : Qt::transparent );
2096 map[QStringLiteral(
"size" )] = QString::number( size );
2098 map[QStringLiteral(
"angle" )] = QString::number(
angle );
2099 if ( !offset.isNull() )
2100 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
2106 if ( layers.isEmpty() )
2109 layerList << layers;
2116 QString patternName;
2117 switch ( brushStyle )
2122 case Qt::SolidPattern:
2123 if ( color.isValid() )
2126 if ( color.alpha() < 255 )
2131 case Qt::CrossPattern:
2132 case Qt::DiagCrossPattern:
2133 case Qt::HorPattern:
2134 case Qt::VerPattern:
2135 case Qt::BDiagPattern:
2136 case Qt::FDiagPattern:
2137 case Qt::Dense1Pattern:
2138 case Qt::Dense2Pattern:
2139 case Qt::Dense3Pattern:
2140 case Qt::Dense4Pattern:
2141 case Qt::Dense5Pattern:
2142 case Qt::Dense6Pattern:
2143 case Qt::Dense7Pattern:
2148 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( brushStyle ) ) );
2152 QDomElement graphicFillElem = doc.createElement( QStringLiteral(
"se:GraphicFill" ) );
2153 element.appendChild( graphicFillElem );
2155 QDomElement graphicElem = doc.createElement( QStringLiteral(
"se:Graphic" ) );
2156 graphicFillElem.appendChild( graphicElem );
2158 const QColor fillColor = patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
2159 const QColor strokeColor = !patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
2162 wellKnownMarkerToSld( doc, graphicElem, patternName, fillColor, strokeColor, Qt::SolidLine, -1, -1 );
2169 brushStyle = Qt::SolidPattern;
2170 color = QColor( 128, 128, 128 );
2172 if ( element.isNull() )
2174 brushStyle = Qt::NoBrush;
2179 const QDomElement graphicFillElem = element.firstChildElement( QStringLiteral(
"GraphicFill" ) );
2181 if ( graphicFillElem.isNull() )
2184 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2186 QgsDebugMsgLevel( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ), 2 );
2188 if ( it.key() == QLatin1String(
"fill" ) )
2189 color = QColor( it.value() );
2190 else if ( it.key() == QLatin1String(
"fill-opacity" ) )
2196 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
2197 if ( graphicElem.isNull() )
2200 QString patternName = QStringLiteral(
"square" );
2201 QColor fillColor, strokeColor;
2202 double strokeWidth, size;
2203 Qt::PenStyle strokeStyle;
2204 if ( !
wellKnownMarkerFromSld( graphicElem, patternName, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
2208 if ( brushStyle == Qt::NoBrush )
2211 const QColor
c = patternName.startsWith( QLatin1String(
"brush://" ) ) ? fillColor : strokeColor;
2220 Qt::PenStyle penStyle,
const QColor &color,
double width,
2221 const Qt::PenJoinStyle *penJoinStyle,
const Qt::PenCapStyle *penCapStyle,
2222 const QVector<qreal> *customDashPattern,
double dashOffset )
2224 QVector<qreal> dashPattern;
2225 const QVector<qreal> *pattern = &dashPattern;
2227 if ( penStyle == Qt::CustomDashLine && !customDashPattern )
2229 element.appendChild( doc.createComment( QStringLiteral(
"WARNING: Custom dash pattern required but not provided. Using default dash pattern." ) ) );
2230 penStyle = Qt::DashLine;
2242 dashPattern.push_back( 4.0 );
2243 dashPattern.push_back( 2.0 );
2246 dashPattern.push_back( 1.0 );
2247 dashPattern.push_back( 2.0 );
2249 case Qt::DashDotLine:
2250 dashPattern.push_back( 4.0 );
2251 dashPattern.push_back( 2.0 );
2252 dashPattern.push_back( 1.0 );
2253 dashPattern.push_back( 2.0 );
2255 case Qt::DashDotDotLine:
2256 dashPattern.push_back( 4.0 );
2257 dashPattern.push_back( 2.0 );
2258 dashPattern.push_back( 1.0 );
2259 dashPattern.push_back( 2.0 );
2260 dashPattern.push_back( 1.0 );
2261 dashPattern.push_back( 2.0 );
2264 case Qt::CustomDashLine:
2265 Q_ASSERT( customDashPattern );
2266 pattern = customDashPattern;
2270 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( penStyle ) ) );
2274 if ( color.isValid() )
2277 if ( color.alpha() < 255 )
2284 else if ( width == 0 )
2294 if ( !pattern->isEmpty() )
2304 Qt::PenStyle &penStyle, QColor &color,
double &width,
2305 Qt::PenJoinStyle *penJoinStyle, Qt::PenCapStyle *penCapStyle,
2306 QVector<qreal> *customDashPattern,
double *dashOffset )
2310 penStyle = Qt::SolidLine;
2311 color = QColor( 0, 0, 0 );
2314 *penJoinStyle = Qt::BevelJoin;
2316 *penCapStyle = Qt::SquareCap;
2317 if ( customDashPattern )
2318 customDashPattern->clear();
2322 if ( element.isNull() )
2324 penStyle = Qt::NoPen;
2330 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2332 QgsDebugMsgLevel( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ), 2 );
2334 if ( it.key() == QLatin1String(
"stroke" ) )
2336 color = QColor( it.value() );
2338 else if ( it.key() == QLatin1String(
"stroke-opacity" ) )
2342 else if ( it.key() == QLatin1String(
"stroke-width" ) )
2345 const double w = it.value().toDouble( &ok );
2349 else if ( it.key() == QLatin1String(
"stroke-linejoin" ) && penJoinStyle )
2353 else if ( it.key() == QLatin1String(
"stroke-linecap" ) && penCapStyle )
2357 else if ( it.key() == QLatin1String(
"stroke-dasharray" ) )
2360 if ( !dashPattern.isEmpty() )
2364 bool dashPatternFound =
false;
2366 if ( dashPattern.count() == 2 )
2368 if ( dashPattern.at( 0 ) == 4.0 &&
2369 dashPattern.at( 1 ) == 2.0 )
2371 penStyle = Qt::DashLine;
2372 dashPatternFound =
true;
2374 else if ( dashPattern.at( 0 ) == 1.0 &&
2375 dashPattern.at( 1 ) == 2.0 )
2377 penStyle = Qt::DotLine;
2378 dashPatternFound =
true;
2381 else if ( dashPattern.count() == 4 )
2383 if ( dashPattern.at( 0 ) == 4.0 &&
2384 dashPattern.at( 1 ) == 2.0 &&
2385 dashPattern.at( 2 ) == 1.0 &&
2386 dashPattern.at( 3 ) == 2.0 )
2388 penStyle = Qt::DashDotLine;
2389 dashPatternFound =
true;
2392 else if ( dashPattern.count() == 6 )
2394 if ( dashPattern.at( 0 ) == 4.0 &&
2395 dashPattern.at( 1 ) == 2.0 &&
2396 dashPattern.at( 2 ) == 1.0 &&
2397 dashPattern.at( 3 ) == 2.0 &&
2398 dashPattern.at( 4 ) == 1.0 &&
2399 dashPattern.at( 5 ) == 2.0 )
2401 penStyle = Qt::DashDotDotLine;
2402 dashPatternFound =
true;
2407 if ( !dashPatternFound )
2409 if ( customDashPattern )
2411 penStyle = Qt::CustomDashLine;
2412 *customDashPattern = dashPattern;
2416 QgsDebugMsgLevel( QStringLiteral(
"custom dash pattern required but not provided. Using default dash pattern." ), 2 );
2417 penStyle = Qt::DashLine;
2422 else if ( it.key() == QLatin1String(
"stroke-dashoffset" ) && dashOffset )
2425 const double d = it.value().toDouble( &ok );
2435 const QString &path,
const QString &mime,
2436 const QColor &color,
double size )
2438 QDomElement externalGraphicElem = doc.createElement( QStringLiteral(
"se:ExternalGraphic" ) );
2439 element.appendChild( externalGraphicElem );
2448 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2450 element.appendChild( sizeElem );
2455 const QString &path,
const QColor &fillColor,
double size,
const QColor &strokeColor,
double strokeWidth )
2462 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Parametric SVG" ) ) );
2463 const QString parametricPath =
getSvgParametricPath( path, fillColor, strokeColor, strokeWidth );
2466 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Plain SVG fallback, no parameters" ) ) );
2469 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Well known marker fallback" ) ) );
2475 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2477 graphicElem.appendChild( sizeElem );
2485 if ( fillColor.isValid() )
2487 url.addQueryItem( QStringLiteral(
"fill" ), fillColor.name() );
2488 url.addQueryItem( QStringLiteral(
"fill-opacity" ),
encodeSldAlpha( fillColor.alpha() ) );
2492 url.addQueryItem( QStringLiteral(
"fill" ), QStringLiteral(
"#000000" ) );
2493 url.addQueryItem( QStringLiteral(
"fill-opacity" ), QStringLiteral(
"1" ) );
2495 if ( strokeColor.isValid() )
2497 url.addQueryItem( QStringLiteral(
"outline" ), strokeColor.name() );
2498 url.addQueryItem( QStringLiteral(
"outline-opacity" ),
encodeSldAlpha( strokeColor.alpha() ) );
2502 url.addQueryItem( QStringLiteral(
"outline" ), QStringLiteral(
"#000000" ) );
2503 url.addQueryItem( QStringLiteral(
"outline-opacity" ), QStringLiteral(
"1" ) );
2505 url.addQueryItem( QStringLiteral(
"outline-width" ), QString::number( strokeWidth ) );
2506 const QString params = url.toString( QUrl::FullyEncoded );
2507 if ( params.isEmpty() )
2513 return basePath +
"?" + params;
2518 QString &path, QString &mime,
2519 QColor &color,
double &size )
2524 QDomElement externalGraphicElem = element.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
2525 if ( externalGraphicElem.isNull() )
2530 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2531 if ( !sizeElem.isNull() )
2534 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2543 const QString &path,
const QString &format,
int *markIndex,
2544 const QColor &color,
double size )
2546 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2547 element.appendChild( markElem );
2553 QDomElement markIndexElem = doc.createElement( QStringLiteral(
"se:MarkIndex" ) );
2554 markIndexElem.appendChild( doc.createTextNode( QString::number( *markIndex ) ) );
2555 markElem.appendChild( markIndexElem );
2559 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2560 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2561 markElem.appendChild( fillElem );
2566 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2568 element.appendChild( sizeElem );
2573 QString &path, QString &format,
int &markIndex,
2574 QColor &color,
double &size )
2582 QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2583 if ( markElem.isNull() )
2588 const QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
2589 if ( !markIndexElem.isNull() )
2592 const int i = markIndexElem.firstChild().nodeValue().toInt( &ok );
2598 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2599 Qt::BrushStyle b = Qt::SolidPattern;
2604 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2605 if ( !sizeElem.isNull() )
2608 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2617 const QString &name,
const QColor &color,
const QColor &strokeColor, Qt::PenStyle strokeStyle,
2618 double strokeWidth,
double size )
2620 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2621 element.appendChild( markElem );
2623 QDomElement wellKnownNameElem = doc.createElement( QStringLiteral(
"se:WellKnownName" ) );
2624 wellKnownNameElem.appendChild( doc.createTextNode( name ) );
2625 markElem.appendChild( wellKnownNameElem );
2628 if ( color.isValid() )
2630 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2631 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2632 markElem.appendChild( fillElem );
2636 if ( strokeColor.isValid() )
2638 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
2639 lineToSld( doc, strokeElem, strokeStyle, strokeColor, strokeWidth );
2640 markElem.appendChild( strokeElem );
2646 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2648 element.appendChild( sizeElem );
2653 QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle,
2654 double &strokeWidth,
double &size )
2658 name = QStringLiteral(
"square" );
2660 strokeColor = QColor( 0, 0, 0 );
2664 const QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2665 if ( markElem.isNull() )
2668 const QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
2669 if ( !wellKnownNameElem.isNull() )
2671 name = wellKnownNameElem.firstChild().nodeValue();
2676 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2677 Qt::BrushStyle b = Qt::SolidPattern;
2682 QDomElement strokeElem = markElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2683 lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth );
2687 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2688 if ( !sizeElem.isNull() )
2691 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2701 if ( !rotationFunc.isEmpty() )
2703 QDomElement rotationElem = doc.createElement( QStringLiteral(
"se:Rotation" ) );
2705 element.appendChild( rotationElem );
2711 QDomElement rotationElem = element.firstChildElement( QStringLiteral(
"Rotation" ) );
2712 if ( !rotationElem.isNull() )
2722 if ( !alphaFunc.isEmpty() )
2724 QDomElement opacityElem = doc.createElement( QStringLiteral(
"se:Opacity" ) );
2726 element.appendChild( opacityElem );
2732 QDomElement opacityElem = element.firstChildElement( QStringLiteral(
"Opacity" ) );
2733 if ( !opacityElem.isNull() )
2742 if ( offset.isNull() )
2745 QDomElement displacementElem = doc.createElement( QStringLiteral(
"se:Displacement" ) );
2746 element.appendChild( displacementElem );
2748 QDomElement dispXElem = doc.createElement( QStringLiteral(
"se:DisplacementX" ) );
2749 dispXElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.x(), 2 ) ) );
2751 QDomElement dispYElem = doc.createElement( QStringLiteral(
"se:DisplacementY" ) );
2752 dispYElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.y(), 2 ) ) );
2754 displacementElem.appendChild( dispXElem );
2755 displacementElem.appendChild( dispYElem );
2762 QDomElement anchorElem = doc.createElement( QStringLiteral(
"se:AnchorPoint" ) );
2763 element.appendChild( anchorElem );
2765 QDomElement anchorXElem = doc.createElement( QStringLiteral(
"se:AnchorPointX" ) );
2766 anchorXElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.x() ) ) );
2768 QDomElement anchorYElem = doc.createElement( QStringLiteral(
"se:AnchorPointY" ) );
2769 anchorYElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.y() ) ) );
2771 anchorElem.appendChild( anchorXElem );
2772 anchorElem.appendChild( anchorYElem );
2777 offset = QPointF( 0, 0 );
2779 const QDomElement displacementElem = element.firstChildElement( QStringLiteral(
"Displacement" ) );
2780 if ( displacementElem.isNull() )
2783 const QDomElement dispXElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementX" ) );
2784 if ( !dispXElem.isNull() )
2787 const double offsetX = dispXElem.firstChild().nodeValue().toDouble( &ok );
2789 offset.setX( offsetX );
2792 const QDomElement dispYElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementY" ) );
2793 if ( !dispYElem.isNull() )
2796 const double offsetY = dispYElem.firstChild().nodeValue().toDouble( &ok );
2798 offset.setY( offsetY );
2805 const QString &label,
const QFont &font,
2806 const QColor &color,
double size )
2808 QDomElement labelElem = doc.createElement( QStringLiteral(
"se:Label" ) );
2809 labelElem.appendChild( doc.createTextNode( label ) );
2810 element.appendChild( labelElem );
2812 QDomElement fontElem = doc.createElement( QStringLiteral(
"se:Font" ) );
2813 element.appendChild( fontElem );
2817 fontElem.appendChild( createSldParameterElement( doc,
"font-style",
encodeSldFontStyle( font.style() ) ) );
2818 fontElem.appendChild( createSldParameterElement( doc,
"font-weight",
encodeSldFontWeight( font.weight() ) ) );
2823 if ( color.isValid() )
2825 QDomElement fillElem = doc.createElement( QStringLiteral(
"Fill" ) );
2826 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2827 element.appendChild( fillElem );
2832 Qt::PenJoinStyle joinStyle,
2833 Qt::PenCapStyle capStyle,
2835 const QVector<qreal> *dashPattern )
2838 penStyle.append(
"PEN(" );
2839 penStyle.append(
"c:" );
2840 penStyle.append(
c.name() );
2841 penStyle.append(
",w:" );
2843 penStyle.append( QString::number( width * mmScaleFactor ) );
2844 penStyle.append(
"mm" );
2847 if ( dashPattern && !dashPattern->isEmpty() )
2849 penStyle.append(
",p:\"" );
2850 QVector<qreal>::const_iterator pIt = dashPattern->constBegin();
2851 for ( ; pIt != dashPattern->constEnd(); ++pIt )
2853 if ( pIt != dashPattern->constBegin() )
2855 penStyle.append(
' ' );
2857 penStyle.append( QString::number( *pIt * mapUnitScaleFactor ) );
2858 penStyle.append(
'g' );
2860 penStyle.append(
'\"' );
2864 penStyle.append(
",cap:" );
2868 penStyle.append(
'p' );
2871 penStyle.append(
'r' );
2875 penStyle.append(
'b' );
2879 penStyle.append(
",j:" );
2880 switch ( joinStyle )
2883 penStyle.append(
'b' );
2886 penStyle.append(
'r' );
2890 penStyle.append(
'm' );
2896 penStyle.append(
",dp:" );
2897 penStyle.append( QString::number( offset * mapUnitScaleFactor ) );
2898 penStyle.append(
'g' );
2901 penStyle.append(
')' );
2908 brushStyle.append(
"BRUSH(" );
2909 brushStyle.append(
"fc:" );
2910 brushStyle.append( fillColor.name() );
2911 brushStyle.append(
')' );
2917 if ( geomFunc.isEmpty() )
2920 QDomElement geometryElem = doc.createElement( QStringLiteral(
"Geometry" ) );
2921 element.appendChild( geometryElem );
2951 QDomElement geometryElem = element.firstChildElement( QStringLiteral(
"Geometry" ) );
2952 if ( geometryElem.isNull() )
2964 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " +
function ) );
2968 if ( !filterElem.isNull() )
2969 element.appendChild( filterElem );
2980 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " +
function ) );
2984 if ( !filterElem.isNull() )
2985 element.appendChild( filterElem );
2992 QDomElement elem = element;
2993 if ( element.tagName() != QLatin1String(
"Filter" ) )
2995 const QDomNodeList filterNodes = element.elementsByTagName( QStringLiteral(
"Filter" ) );
2996 if ( !filterNodes.isEmpty() )
2998 elem = filterNodes.at( 0 ).toElement();
3002 if ( elem.isNull() )
3027 const QString &path,
const QString &format )
3031 QDomElement onlineResourceElem = doc.createElement( QStringLiteral(
"se:OnlineResource" ) );
3032 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
3033 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:href" ), url );
3034 element.appendChild( onlineResourceElem );
3036 QDomElement formatElem = doc.createElement( QStringLiteral(
"se:Format" ) );
3037 formatElem.appendChild( doc.createTextNode( format ) );
3038 element.appendChild( formatElem );
3045 const QDomElement onlineResourceElem = element.firstChildElement( QStringLiteral(
"OnlineResource" ) );
3046 if ( onlineResourceElem.isNull() )
3049 path = QUrl::fromPercentEncoding( onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) ).toUtf8() );
3051 const QDomElement formatElem = element.firstChildElement( QStringLiteral(
"Format" ) );
3052 if ( formatElem.isNull() )
3055 format = formatElem.firstChild().nodeValue();
3062 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:SvgParameter" ) );
3063 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
3064 nodeElem.appendChild( doc.createTextNode( value ) );
3073 QDomElement paramElem = element.firstChildElement();
3074 while ( !paramElem.isNull() )
3076 if ( paramElem.localName() == QLatin1String(
"SvgParameter" ) || paramElem.localName() == QLatin1String(
"CssParameter" ) )
3078 const QString name = paramElem.attribute( QStringLiteral(
"name" ) );
3079 if ( paramElem.firstChild().nodeType() == QDomNode::TextNode )
3081 value = paramElem.firstChild().nodeValue();
3085 if ( paramElem.firstChild().nodeType() == QDomNode::ElementNode &&
3086 paramElem.firstChild().localName() == QLatin1String(
"Literal" ) )
3089 value = paramElem.firstChild().firstChild().nodeValue();
3093 QgsDebugMsg( QStringLiteral(
"unexpected child of %1" ).arg( paramElem.localName() ) );
3097 if ( !name.isEmpty() && !value.isEmpty() )
3098 params[ name ] = value;
3101 paramElem = paramElem.nextSiblingElement();
3109 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:VendorOption" ) );
3110 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
3111 nodeElem.appendChild( doc.createTextNode( value ) );
3119 QDomElement paramElem = element.firstChildElement( QStringLiteral(
"VendorOption" ) );
3120 while ( !paramElem.isNull() )
3122 const QString name = paramElem.attribute( QStringLiteral(
"name" ) );
3123 const QString value = paramElem.firstChild().nodeValue();
3125 if ( !name.isEmpty() && !value.isEmpty() )
3126 params[ name ] = value;
3128 paramElem = paramElem.nextSiblingElement( QStringLiteral(
"VendorOption" ) );
3138 if ( newSymbols.type() == QVariant::Map )
3140 return newSymbols.toMap();
3147 QDomElement e = element.firstChildElement();
3148 while ( !e.isNull() )
3150 if ( e.tagName() == QLatin1String(
"prop" ) )
3152 const QString propKey = e.attribute( QStringLiteral(
"k" ) );
3153 const QString propValue = e.attribute( QStringLiteral(
"v" ) );
3154 props[propKey] = propValue;
3156 e = e.nextSiblingElement();
3171 for ( QVariantMap::iterator it = props.begin(); it != props.end(); ++it )
3173 QDomElement propEl = doc.createElement( QStringLiteral(
"prop" ) );
3174 propEl.setAttribute( QStringLiteral(
"k" ), it.key() );
3175 propEl.setAttribute( QStringLiteral(
"v" ), it.value().toString() );
3176 element.appendChild( propEl );
3186 QDomElement e = element.firstChildElement();
3188 while ( !e.isNull() )
3190 if ( e.tagName() == QLatin1String(
"symbol" ) )
3194 symbols.insert( e.attribute( QStringLiteral(
"name" ) ), symbol );
3200 e = e.nextSiblingElement();
3207 QStringList subsymbols;
3209 for ( QMap<QString, QgsSymbol *>::iterator it = symbols.begin(); it != symbols.end(); ++it )
3211 if ( it.key()[0] !=
'@' )
3215 subsymbols.append( it.key() );
3217 QStringList parts = it.key().split(
'@' );
3218 if ( parts.count() < 3 )
3220 QgsDebugMsg(
"found subsymbol with invalid name: " + it.key() );
3224 const QString symname = parts[1];
3225 const int symlayer = parts[2].toInt();
3227 if ( !symbols.contains( symname ) )
3229 QgsDebugMsg(
"subsymbol references invalid symbol: " + symname );
3237 QgsDebugMsg(
"subsymbol references invalid symbol layer: " + QString::number( symlayer ) );
3246 QgsDebugMsg(
"symbol layer refused subsymbol: " + it.key() );
3253 for (
int i = 0; i < subsymbols.count(); i++ )
3254 symbols.take( subsymbols[i] );
3261 QDomElement symbolsElem = doc.createElement( tagName );
3264 for ( QMap<QString, QgsSymbol *>::iterator its = symbols.begin(); its != symbols.end(); ++its )
3266 const QDomElement symEl =
saveSymbol( its.key(), its.value(), doc, context );
3267 symbolsElem.appendChild( symEl );
3275 qDeleteAll( symbols );
3284 std::unique_ptr< QMimeData >mimeData(
new QMimeData );
3286 QDomDocument symbolDoc;
3288 symbolDoc.appendChild( symbolElem );
3289 mimeData->setText( symbolDoc.toString() );
3292 mimeData->setColorData( symbol->
color() );
3294 return mimeData.release();
3302 const QString text = data->text();
3303 if ( !text.isEmpty() )
3308 if ( doc.setContent( text ) )
3310 elem = doc.documentElement();
3312 if ( elem.nodeName() != QLatin1String(
"symbol" ) )
3313 elem = elem.firstChildElement( QStringLiteral(
"symbol" ) );
3324 const QString rampType = element.attribute( QStringLiteral(
"type" ) );
3341 QgsDebugMsg(
"unknown colorramp type " + rampType );
3349 QDomElement rampEl = doc.createElement( QStringLiteral(
"colorramp" ) );
3350 rampEl.setAttribute( QStringLiteral(
"type" ), ramp->
type() );
3351 rampEl.setAttribute( QStringLiteral(
"name" ), name );
3359 QVariantMap rampMap;
3361 rampMap.insert( QStringLiteral(
"type" ), ramp->
type() );
3362 rampMap.insert( QStringLiteral(
"name" ), name );
3364 const QVariantMap properties = ramp->
properties();
3366 QVariantMap propertyMap;
3367 for (
auto property = properties.constBegin(); property != properties.constEnd(); ++property )
3369 propertyMap.insert( property.key(), property.value() );
3372 rampMap.insert( QStringLiteral(
"properties" ), propertyMap );
3378 const QVariantMap rampMap = value.toMap();
3380 const QString rampType = rampMap.
value( QStringLiteral(
"type" ) ).toString();
3383 const QVariantMap propertyMap = rampMap.value( QStringLiteral(
"properties" ) ).toMap();
3386 for (
auto property = propertyMap.constBegin(); property != propertyMap.constEnd(); ++property )
3388 props.insert( property.key(), property.value().toString() );
3403 QgsDebugMsg(
"unknown colorramp type " + rampType );
3410 if ( !color.isValid() )
3417 return color.name();
3422 QList<QColor> colors;
3425 const thread_local QRegularExpression sepCommaSpaceRegExp(
"(,|\\s)" );
3426 QStringList components = colorStr.simplified().split( sepCommaSpaceRegExp );
3427 QStringList::iterator it = components.begin();
3428 for ( ; it != components.end(); ++it )
3430 const QColor result =
parseColor( *it,
true );
3431 if ( result.isValid() )
3436 if ( colors.length() > 0 )
3442 const thread_local QRegularExpression sepCommaRegExp(
"(,|\n)" );
3443 components = colorStr.split( sepCommaRegExp );
3444 it = components.begin();
3445 for ( ; it != components.end(); ++it )
3447 const QColor result =
parseColor( *it,
true );
3448 if ( result.isValid() )
3453 if ( colors.length() > 0 )
3459 components = colorStr.simplified().split( QString(
' ' ) );
3460 it = components.begin();
3461 for ( ; it != components.end(); ++it )
3463 const QColor result =
parseColor( *it,
true );
3464 if ( result.isValid() )
3469 if ( colors.length() > 0 )
3475 components = colorStr.split(
'\n' );
3476 it = components.begin();
3477 for ( ; it != components.end(); ++it )
3479 const QColor result =
parseColor( *it,
true );
3480 if ( result.isValid() )
3493 QMimeData *mimeData =
new QMimeData;
3494 mimeData->setColorData( QVariant( color ) );
3495 mimeData->setText( color.name() );
3502 if ( mimeData->hasColor() )
3504 QColor mimeColor = mimeData->colorData().value<QColor>();
3505 if ( mimeColor.isValid() )
3513 if ( mimeData->hasText() )
3517 if ( textColor.isValid() )
3532 if ( data->hasFormat( QStringLiteral(
"text/xml" ) ) )
3535 const QByteArray encodedData = data->data( QStringLiteral(
"text/xml" ) );
3536 QDomDocument xmlDoc;
3537 xmlDoc.setContent( encodedData );
3539 const QDomElement dragDataElem = xmlDoc.documentElement();
3540 if ( dragDataElem.tagName() == QLatin1String(
"ColorSchemeModelDragData" ) )
3542 const QDomNodeList nodeList = dragDataElem.childNodes();
3543 const int nChildNodes = nodeList.size();
3544 QDomElement currentElem;
3546 for (
int i = 0; i < nChildNodes; ++i )
3548 currentElem = nodeList.at( i ).toElement();
3549 if ( currentElem.isNull() )
3554 QPair< QColor, QString> namedColor;
3556 namedColor.second = currentElem.attribute( QStringLiteral(
"label" ), QString() );
3558 mimeColors << namedColor;
3563 if ( mimeColors.length() == 0 && data->hasFormat( QStringLiteral(
"application/x-colorobject-list" ) ) )
3566 const QByteArray encodedData = data->data( QStringLiteral(
"application/x-colorobject-list" ) );
3567 QDomDocument xmlDoc;
3568 xmlDoc.setContent( encodedData );
3570 const QDomNodeList colorsNodes = xmlDoc.elementsByTagName( QStringLiteral(
"colors" ) );
3571 if ( colorsNodes.length() > 0 )
3573 const QDomElement colorsElem = colorsNodes.at( 0 ).toElement();
3574 const QDomNodeList colorNodeList = colorsElem.childNodes();
3575 const int nChildNodes = colorNodeList.size();
3576 QDomElement currentElem;
3578 for (
int i = 0; i < nChildNodes; ++i )
3581 currentElem = colorNodeList.at( i ).toElement();
3582 if ( currentElem.isNull() )
3587 const QDomNodeList colorNodes = currentElem.elementsByTagName( QStringLiteral(
"color" ) );
3588 const QDomNodeList nameNodes = currentElem.elementsByTagName( QStringLiteral(
"name" ) );
3590 if ( colorNodes.length() > 0 )
3592 const QDomElement colorElem = colorNodes.at( 0 ).toElement();
3594 const QStringList colorParts = colorElem.text().simplified().split(
' ' );
3595 if ( colorParts.length() < 3 )
3600 const int red = colorParts.at( 0 ).toDouble() * 255;
3601 const int green = colorParts.at( 1 ).toDouble() * 255;
3602 const int blue = colorParts.at( 2 ).toDouble() * 255;
3603 QPair< QColor, QString> namedColor;
3604 namedColor.first = QColor( red, green, blue );
3605 if ( nameNodes.length() > 0 )
3607 const QDomElement nameElem = nameNodes.at( 0 ).toElement();
3608 namedColor.second = nameElem.text();
3610 mimeColors << namedColor;
3616 if ( mimeColors.length() == 0 && data->hasText() )
3620 QList< QColor >::iterator it = parsedColors.begin();
3621 for ( ; it != parsedColors.end(); ++it )
3623 mimeColors << qMakePair( *it, QString() );
3627 if ( mimeColors.length() == 0 && data->hasColor() )
3630 const QColor mimeColor = data->colorData().value<QColor>();
3631 if ( mimeColor.isValid() )
3633 mimeColors << qMakePair( mimeColor, QString() );
3643 QMimeData *mimeData =
new QMimeData();
3644 QDomDocument xmlDoc;
3645 QDomElement xmlRootElement = xmlDoc.createElement( QStringLiteral(
"ColorSchemeModelDragData" ) );
3646 xmlDoc.appendChild( xmlRootElement );
3648 QgsNamedColorList::const_iterator colorIt = colorList.constBegin();
3649 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3651 QDomElement namedColor = xmlDoc.createElement( QStringLiteral(
"NamedColor" ) );
3653 namedColor.setAttribute( QStringLiteral(
"label" ), ( *colorIt ).second );
3654 xmlRootElement.appendChild( namedColor );
3656 mimeData->setData( QStringLiteral(
"text/xml" ), xmlDoc.toByteArray() );
3664 colorIt = colorList.constBegin();
3665 QStringList colorListString;
3666 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3668 colorListString << ( *colorIt ).first.name();
3670 mimeData->setText( colorListString.join( QLatin1Char(
'\n' ) ) );
3673 if ( colorList.length() > 0 )
3675 mimeData->setColorData( QVariant( colorList.at( 0 ).first ) );
3683 if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3688 QTextStream stream( &file );
3689 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3690 stream <<
"GIMP Palette" << endl;
3692 stream <<
"GIMP Palette" << Qt::endl;
3694 if ( paletteName.isEmpty() )
3696 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3697 stream <<
"Name: QGIS Palette" << endl;
3699 stream <<
"Name: QGIS Palette" << Qt::endl;
3704 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3705 stream <<
"Name: " << paletteName << endl;
3707 stream <<
"Name: " << paletteName << Qt::endl;
3710 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3711 stream <<
"Columns: 4" << endl;
3712 stream <<
'#' << endl;
3714 stream <<
"Columns: 4" << Qt::endl;
3715 stream <<
'#' << Qt::endl;
3718 for ( QgsNamedColorList::ConstIterator colorIt = colors.constBegin(); colorIt != colors.constEnd(); ++colorIt )
3720 const QColor color = ( *colorIt ).first;
3721 if ( !color.isValid() )
3725 stream << QStringLiteral(
"%1 %2 %3" ).arg( color.red(), 3 ).arg( color.green(), 3 ).arg( color.blue(), 3 );
3726 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3727 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << endl;
3729 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << Qt::endl;
3741 if ( !file.open( QIODevice::ReadOnly ) )
3744 return importedColors;
3747 QTextStream in( &file );
3749 QString line = in.readLine();
3750 if ( !line.startsWith( QLatin1String(
"GIMP Palette" ) ) )
3753 return importedColors;
3757 while ( !in.atEnd() && !line.startsWith( QLatin1String(
"Name:" ) ) && !line.startsWith(
'#' ) )
3759 line = in.readLine();
3761 if ( line.startsWith( QLatin1String(
"Name:" ) ) )
3763 const thread_local QRegularExpression nameRx(
"Name:\\s*(\\S.*)$" );
3764 const QRegularExpressionMatch match = nameRx.match( line );
3765 if ( match.hasMatch() )
3767 name = match.captured( 1 );
3772 while ( !in.atEnd() && !line.startsWith(
'#' ) )
3774 line = in.readLine();
3779 return importedColors;
3783 const thread_local QRegularExpression rx(
"^\\s*(\\d+)\\s+(\\d+)\\s+(\\d+)(\\s.*)?$" );
3784 while ( !in.atEnd() )
3786 line = in.readLine();
3787 const QRegularExpressionMatch match = rx.match( line );
3788 if ( !match.hasMatch() )
3792 const int red = match.captured( 1 ).toInt();
3793 const int green = match.captured( 2 ).toInt();
3794 const int blue = match.captured( 3 ).toInt();
3795 const QColor color = QColor( red, green, blue );
3796 if ( !color.isValid() )
3803 if ( rx.captureCount() > 3 )
3805 label = match.captured( 4 ).simplified();
3812 importedColors << qMakePair( color, label );
3817 return importedColors;
3830 const thread_local QRegularExpression hexColorAlphaRx(
"^\\s*#?([0-9a-fA-F]{6})([0-9a-fA-F]{2})\\s*$" );
3831 QRegularExpressionMatch match = hexColorAlphaRx.match( colorStr );
3834 if ( !match.hasMatch() && QColor::isValidColor( colorStr ) )
3837 parsedColor.setNamedColor( colorStr );
3838 if ( parsedColor.isValid() )
3840 containsAlpha =
false;
3846 if ( match.hasMatch() )
3848 const QString hexColor = match.captured( 1 );
3849 parsedColor.setNamedColor( QStringLiteral(
"#" ) + hexColor );
3851 const int alphaHex = match.captured( 2 ).toInt( &alphaOk, 16 );
3853 if ( parsedColor.isValid() && alphaOk )
3855 parsedColor.setAlpha( alphaHex );
3856 containsAlpha =
true;
3864 const thread_local QRegularExpression hexColorRx2(
"^\\s*(?:[0-9a-fA-F]{3}){1,2}\\s*$" );
3865 if ( colorStr.indexOf( hexColorRx2 ) != -1 )
3868 parsedColor.setNamedColor( QStringLiteral(
"#" ) + colorStr );
3869 if ( parsedColor.isValid() )
3871 containsAlpha =
false;
3878 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*$" );
3879 match = rgbFormatRx.match( colorStr );
3880 if ( match.hasMatch() )
3882 const int r = match.captured( 1 ).toInt();
3883 const int g = match.captured( 2 ).toInt();
3884 const int b = match.captured( 3 ).toInt();
3885 parsedColor.setRgb( r, g, b );
3886 if ( parsedColor.isValid() )
3888 containsAlpha =
false;
3894 const thread_local QRegularExpression hslFormatRx(
"^\\s*hsl\\(?\\s*(\\d+)\\s*,\\s*(\\d+)\\s*%\\s*,\\s*(\\d+)\\s*%\\s*\\)?\\s*;?\\s*$" );
3895 match = hslFormatRx.match( colorStr );
3896 if ( match.hasMatch() )
3898 const int h = match.captured( 1 ).toInt();
3899 const int s = match.captured( 2 ).toInt();
3900 const int l = match.captured( 3 ).toInt();
3901 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0 );
3902 if ( parsedColor.isValid() )
3904 containsAlpha =
false;
3910 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*$" );
3911 match = rgbPercentFormatRx.match( colorStr );
3912 if ( match.hasMatch() )
3914 const int r = std::round( match.captured( 1 ).toDouble() * 2.55 );
3915 const int g = std::round( match.captured( 2 ).toDouble() * 2.55 );
3916 const int b = std::round( match.captured( 3 ).toDouble() * 2.55 );
3917 parsedColor.setRgb( r, g, b );
3918 if ( parsedColor.isValid() )
3920 containsAlpha =
false;
3926 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*$" );
3927 match = rgbaFormatRx.match( colorStr );
3928 if ( match.hasMatch() )
3930 const int r = match.captured( 1 ).toInt();
3931 const int g = match.captured( 2 ).toInt();
3932 const int b = match.captured( 3 ).toInt();
3933 const int a = std::round( match.captured( 4 ).toDouble() * 255.0 );
3934 parsedColor.setRgb( r, g, b, a );
3935 if ( parsedColor.isValid() )
3937 containsAlpha =
true;
3943 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*$" );
3944 match = rgbaPercentFormatRx.match( colorStr );
3945 if ( match.hasMatch() )
3947 const int r = std::round( match.captured( 1 ).toDouble() * 2.55 );
3948 const int g = std::round( match.captured( 2 ).toDouble() * 2.55 );
3949 const int b = std::round( match.captured( 3 ).toDouble() * 2.55 );
3950 const int a = std::round( match.captured( 4 ).toDouble() * 255.0 );
3951 parsedColor.setRgb( r, g, b, a );
3952 if ( parsedColor.isValid() )
3954 containsAlpha =
true;
3960 const thread_local QRegularExpression hslaPercentFormatRx(
"^\\s*hsla\\(?\\s*(\\d+)\\s*,\\s*(\\d+)\\s*%\\s*,\\s*(\\d+)\\s*%\\s*,\\s*([\\d\\.]+)\\s*\\)?\\s*;?\\s*$" );
3961 match = hslaPercentFormatRx.match( colorStr );
3962 if ( match.hasMatch() )
3964 const int h = match.captured( 1 ).toInt();
3965 const int s = match.captured( 2 ).toInt();
3966 const int l = match.captured( 3 ).toInt();
3967 const int a = std::round( match.captured( 4 ).toDouble() * 255.0 );
3968 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0, a );
3969 if ( parsedColor.isValid() )
3971 containsAlpha =
true;
3988 const QImage::Format format = image->format();
3989 if ( format != QImage::Format_ARGB32_Premultiplied && format != QImage::Format_ARGB32 )
3991 QgsDebugMsg( QStringLiteral(
"no alpha channel." ) );
3996 for (
int heightIndex = 0; heightIndex < image->height(); ++heightIndex )
3998 QRgb *scanLine =
reinterpret_cast< QRgb *
>( image->scanLine( heightIndex ) );
3999 for (
int widthIndex = 0; widthIndex < image->width(); ++widthIndex )
4001 myRgb = scanLine[widthIndex];
4002 if ( format == QImage::Format_ARGB32_Premultiplied )
4003 scanLine[widthIndex] = qRgba( opacity * qRed( myRgb ), opacity * qGreen( myRgb ), opacity * qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4005 scanLine[widthIndex] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), opacity * qAlpha( myRgb ) );
4013 const int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
4014 const int alpha = ( radius < 1 ) ? 16 : ( radius > 17 ) ? 1 : tab[radius - 1];
4016 if ( image.format() != QImage::Format_ARGB32_Premultiplied
4017 && image.format() != QImage::Format_RGB32 )
4019 image = image.convertToFormat( QImage::Format_ARGB32_Premultiplied );
4022 const int r1 = rect.top();
4023 const int r2 = rect.bottom();
4024 const int c1 = rect.left();
4025 const int c2 = rect.right();
4027 const int bpl = image.bytesPerLine();
4035 i1 = i2 = ( QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3 );
4037 for (
int col = c1; col <= c2; col++ )
4039 p = image.scanLine( r1 ) + col * 4;
4040 for (
int i = i1; i <= i2; i++ )
4041 rgba[i] = p[i] << 4;
4044 for (
int j = r1; j < r2; j++, p += bpl )
4045 for (
int i = i1; i <= i2; i++ )
4046 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4049 for (
int row = r1; row <= r2; row++ )
4051 p = image.scanLine( row ) + c1 * 4;
4052 for (
int i = i1; i <= i2; i++ )
4053 rgba[i] = p[i] << 4;
4056 for (
int j = c1; j < c2; j++, p += 4 )
4057 for (
int i = i1; i <= i2; i++ )
4058 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4061 for (
int col = c1; col <= c2; col++ )
4063 p = image.scanLine( r2 ) + col * 4;
4064 for (
int i = i1; i <= i2; i++ )
4065 rgba[i] = p[i] << 4;
4068 for (
int j = r1; j < r2; j++, p -= bpl )
4069 for (
int i = i1; i <= i2; i++ )
4070 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4073 for (
int row = r1; row <= r2; row++ )
4075 p = image.scanLine( row ) + c2 * 4;
4076 for (
int i = i1; i <= i2; i++ )
4077 rgba[i] = p[i] << 4;
4080 for (
int j = c1; j < c2; j++, p -= 4 )
4081 for (
int i = i1; i <= i2; i++ )
4082 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
4088 if ( alpha != 255 && alpha > 0 )
4092 const double alphaFactor = alpha / 255.;
4093 int r = 0, g = 0, b = 0;
4094 rgb.getRgb( &r, &g, &b );
4099 rgb.setRgb( r, g, b, alpha );
4101 else if ( alpha == 0 )
4103 rgb.setRgb( 0, 0, 0, 0 );
4112 if ( !simpleFill || !simpleLine )
4136 if ( simpleLine->
offset() )
4154 if ( order == Qt::AscendingOrder )
4168 const double dx = directionPoint.x() - startPoint.x();
4169 const double dy = directionPoint.y() - startPoint.y();
4170 const double length = std::sqrt( dx * dx + dy * dy );
4171 const double scaleFactor = distance / length;
4172 return QPointF( startPoint.x() + dx * scaleFactor, startPoint.y() + dy * scaleFactor );
4182 for (
int i = 0; i < svgPaths.size(); i++ )
4184 const QDir dir( svgPaths[i] );
4185 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4186 for (
const QString &item : svgSubPaths )
4188 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4191 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4192 for (
const QString &item : svgFiles )
4195 list.append( dir.path() +
'/' + item );
4207 QStringList svgPaths;
4208 svgPaths.append( directory );
4210 for (
int i = 0; i < svgPaths.size(); i++ )
4212 const QDir dir( svgPaths[i] );
4213 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4214 for (
const QString &item : svgSubPaths )
4216 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4219 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4220 for (
const QString &item : svgFiles )
4222 list.append( dir.path() +
'/' + item );
4234 if ( n.startsWith( QLatin1String(
"base64:" ) ) )
4238 if ( QFileInfo::exists( n ) )
4239 return QFileInfo( n ).canonicalFilePath();
4243 if ( name.contains( QLatin1String(
"://" ) ) )
4245 const QUrl url( name );
4246 if ( url.isValid() && !url.scheme().isEmpty() )
4248 if ( url.scheme().compare( QLatin1String(
"file" ), Qt::CaseInsensitive ) == 0 )
4251 name = url.toLocalFile();
4252 if ( QFile( name ).exists() )
4254 return QFileInfo( name ).canonicalFilePath();
4268 for (
int i = 0; i < svgPaths.size(); i++ )
4270 QString svgPath = svgPaths[i];
4271 if ( svgPath.endsWith( QChar(
'/' ) ) )
4282 const QString myLocalPath = svgPath + QDir::separator() + name;
4285 if ( QFile( myLocalPath ).exists() )
4288 return QFileInfo( myLocalPath ).canonicalFilePath();
4292 return pathResolver.
readPath( name );
4300 if ( p.startsWith( QLatin1String(
"base64:" ) ) )
4303 if ( !QFileInfo::exists( p ) )
4306 QString path = QFileInfo( p ).canonicalFilePath();
4310 bool isInSvgPaths =
false;
4311 for (
int i = 0; i < svgPaths.size(); i++ )
4313 const QString dir = QFileInfo( svgPaths[i] ).canonicalFilePath();
4315 if ( !dir.isEmpty() && path.startsWith( dir ) )
4317 path = path.mid( dir.size() + 1 );
4318 isInSvgPaths =
true;
4333 double cx = 0, cy = 0;
4334 double area, sum = 0;
4335 for (
int i = points.count() - 1, j = 0; j < points.count(); i = j++ )
4337 const QPointF &p1 = points[i];
4338 const QPointF &p2 = points[j];
4339 area = p1.x() * p2.y() - p1.y() * p2.x();
4341 cx += ( p1.x() + p2.x() ) * area;
4342 cy += ( p1.y() + p2.y() ) * area;
4349 if ( points.count() >= 2 )
4350 return QPointF( ( points[0].x() + points[1].x() ) / 2, ( points[0].y() + points[1].y() ) / 2 );
4351 else if ( points.count() == 1 )
4359 return QPointF( cx, cy );
4368 unsigned int i, pointCount = points.count();
4370 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( points[i].x(), points[i].y() );
4376 for (
auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
4378 pointCount = ( *ringIt ).count();
4380 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( ( *ringIt )[i].x(), ( *ringIt )[i].y() );
4386 if ( !pointOnSurfaceGeom.
isNull() )
4400 bool inside =
false;
4402 const double x = point.x();
4403 const double y = point.y();
4405 for (
int i = 0, j = points.count() - 1; i < points.count(); i++ )
4407 const QPointF &p1 = points[i];
4408 const QPointF &p2 = points[j];
4413 if ( ( p1.y() < y && p2.y() >= y ) || ( p2.y() < y && p1.y() >= y ) )
4415 if ( p1.x() + ( y - p1.y() ) / ( p2.y() - p1.y() ) * ( p2.x() - p1.x() ) <= x )
4426 if ( polyline.size() < 2 )
4429 double totalLength = 0;
4430 auto it = polyline.begin();
4432 for ( ; it != polyline.end(); ++it )
4434 const QPointF p2 = *it;
4435 const double segmentLength = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4436 totalLength += segmentLength;
4444 if ( polyline.size() < 2 )
4447 double totalLength = 0;
4448 auto it = polyline.begin();
4450 std::vector< double > segmentLengths( polyline.size() - 1 );
4451 auto segmentLengthIt = segmentLengths.begin();
4452 for ( ; it != polyline.end(); ++it )
4454 const QPointF p2 = *it;
4455 *segmentLengthIt = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4456 totalLength += *segmentLengthIt;
4462 if ( startOffset >= 0 && totalLength <= startOffset )
4464 if ( endOffset < 0 && totalLength <= -endOffset )
4467 const double startDistance = startOffset < 0 ? totalLength + startOffset : startOffset;
4468 const double endDistance = endOffset <= 0 ? totalLength + endOffset : endOffset;
4469 QPolygonF substringPoints;
4470 substringPoints.reserve( polyline.size() );
4472 it = polyline.begin();
4473 segmentLengthIt = segmentLengths.begin();
4476 bool foundStart =
false;
4477 if (
qgsDoubleNear( startDistance, 0.0 ) || startDistance < 0 )
4479 substringPoints << p1;
4483 double distanceTraversed = 0;
4484 for ( ; it != polyline.end(); ++it )
4486 const QPointF p2 = *it;
4487 if ( distanceTraversed < startDistance && distanceTraversed + *segmentLengthIt > startDistance )
4490 const double distanceToStart = startDistance - distanceTraversed;
4491 double startX, startY;
4493 substringPoints << QPointF( startX, startY );
4496 if ( foundStart && ( distanceTraversed + *segmentLengthIt > endDistance ) )
4499 const double distanceToEnd = endDistance - distanceTraversed;
4502 if ( substringPoints.last() != QPointF( endX, endY ) )
4503 substringPoints << QPointF( endX, endY );
4505 else if ( foundStart )
4507 if ( substringPoints.last() != QPointF( p2.x(), p2.y() ) )
4508 substringPoints << QPointF( p2.x(), p2.y() );
4511 distanceTraversed += *segmentLengthIt;
4512 if ( distanceTraversed > endDistance )
4519 if ( ( substringPoints.size() < 2 ) || ( substringPoints.size() == 2 && substringPoints.at( 0 ) == substringPoints.at( 1 ) ) )
4522 return substringPoints;
4527 double vertexAngle = M_PI - ( std::atan2( p3.y() - p2.y(), p3.x() - p2.x() ) - std::atan2( p2.y() - p1.y(), p2.x() - p1.x() ) );
4531 return vertexAngle < M_PI * 135.0 / 180.0 || vertexAngle > M_PI * 225.0 / 180.0;
4536 target.reserve( target.size() + line.size() );
4537 for (
const QPointF &pt : line )
4539 if ( !target.empty() && target.last() == pt )
4548 if ( fieldOrExpression.isEmpty() )
4583 QList<double> breaks;
4586 breaks.append( maximum );
4590 const int minimumCount =
static_cast< int >( classes ) / 3;
4591 const double shrink = 0.75;
4592 const double highBias = 1.5;
4593 const double adjustBias = 0.5 + 1.5 * highBias;
4594 const int divisions = classes;
4595 const double h = highBias;
4598 const double dx = maximum - minimum;
4608 cell = std::max( std::fabs( minimum ), std::fabs( maximum ) );
4609 if ( adjustBias >= 1.5 * h + 0.5 )
4611 U = 1 + ( 1.0 / ( 1 + h ) );
4615 U = 1 + ( 1.5 / ( 1 + adjustBias ) );
4617 small = dx < ( cell * U * std::max( 1, divisions ) * 1e-07 * 3.0 );
4624 cell = 9 + cell / 10;
4625 cell = cell * shrink;
4627 if ( minimumCount > 1 )
4629 cell = cell / minimumCount;
4635 if ( divisions > 1 )
4637 cell = cell / divisions;
4640 if ( cell < 20 * 1e-07 )
4645 const double base = std::pow( 10.0, std::floor( std::log10( cell ) ) );
4647 if ( ( 2 * base ) - cell < h * ( cell - unit ) )
4650 if ( ( 5 * base ) - cell < adjustBias * ( cell - unit ) )
4653 if ( ( 10.0 * base ) - cell < h * ( cell - unit ) )
4660 int start = std::floor( minimum / unit + 1e-07 );
4661 int end = std::ceil( maximum / unit - 1e-07 );
4664 while ( start * unit > minimum + ( 1e-07 * unit ) )
4668 while ( end * unit < maximum - ( 1e-07 * unit ) )
4676 int k = std::floor( 0.5 + end - start );
4677 if ( k < minimumCount )
4679 k = minimumCount - k;
4683 start = start - k / 2 + k % 2;
4687 start = start - k / 2;
4688 end = end + k / 2 + k % 2;
4691 const double minimumBreak = start * unit;
4693 const int count = end - start;
4695 breaks.reserve( count );
4696 for (
int i = 1; i < count + 1; i++ )
4698 breaks.append( minimumBreak + i * unit );
4701 if ( breaks.isEmpty() )
4704 if ( breaks.first() < minimum )
4706 breaks[0] = minimum;
4708 if ( breaks.last() > maximum )
4710 breaks[breaks.count() - 1] = maximum;
4715 if ( minimum < 0.0 && maximum > 0.0 )
4717 QList<double> breaksMinusZero;
4718 for (
int i = 0; i < breaks.count(); i++ )
4720 breaksMinusZero.append( breaks[i] - 0.0 );
4723 for (
int i = 1; i < breaks.count(); i++ )
4725 if ( std::abs( breaksMinusZero[i] ) < std::abs( breaksMinusZero[i - 1] ) )
4728 breaks[posOfMin] = 0.0;
4737 bool roundToUnit =
false;
4740 if ( props.contains( QStringLiteral(
"uomScale" ) ) )
4743 scale = props.value( QStringLiteral(
"uomScale" ) ).toDouble( &ok );
4752 if ( props.value( QStringLiteral(
"uom" ) ) == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
4777 scale = 1 / 0.28 * 25.4;
4801 double rescaled = size * scale;
4806 rescaled = std::round( rescaled );
4813 const double x =
rescaleUom( point.x(), unit, props );
4814 const double y =
rescaleUom( point.y(), unit, props );
4815 return QPointF( x, y );
4820 QVector<qreal> result;
4821 QVector<qreal>::const_iterator it = array.constBegin();
4822 for ( ; it != array.constEnd(); ++it )
4824 result.append(
rescaleUom( *it, unit, props ) );
4831 if ( !props.value( QStringLiteral(
"scaleMinDenom" ), QString() ).toString().isEmpty() )
4833 QDomElement scaleMinDenomElem = doc.createElement( QStringLiteral(
"se:MinScaleDenominator" ) );
4834 scaleMinDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMinDenom" ) ).toString().toDouble() ) ) );
4835 ruleElem.appendChild( scaleMinDenomElem );
4838 if ( !props.value( QStringLiteral(
"scaleMaxDenom" ), QString() ).toString().isEmpty() )
4840 QDomElement scaleMaxDenomElem = doc.createElement( QStringLiteral(
"se:MaxScaleDenominator" ) );
4841 scaleMaxDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMaxDenom" ) ).toString().toDouble() ) ) );
4842 ruleElem.appendChild( scaleMaxDenomElem );
4851 const double parentScaleMinDenom = props.value( QStringLiteral(
"scaleMinDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
4852 if ( !ok || parentScaleMinDenom <= 0 )
4853 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( mScaleMinDenom );
4855 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( std::max( parentScaleMinDenom, mScaleMinDenom ) );
4861 const double parentScaleMaxDenom = props.value( QStringLiteral(
"scaleMaxDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
4862 if ( !ok || parentScaleMaxDenom <= 0 )
4863 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( mScaleMaxDenom );
4865 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( std::min( parentScaleMaxDenom, mScaleMaxDenom ) );
4873 if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
4875 scale = 1.0 / 0.00028;
4877 else if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
4879 scale = 304.8 / 0.28;
4886 return size * scale;
4894 SymbolLayerVisitor(
const QSet<QgsSymbolLayerId> &layerIds )
4895 : mSymbolLayerIds( layerIds )
4908 void visitSymbol(
const QgsSymbol *symbol,
const QString &identifier, QVector<int> rootPath )
4912 QVector<int> indexPath = rootPath;
4913 indexPath.append( idx );
4915 if ( mSymbolLayerIds.contains(
QgsSymbolLayerId( mCurrentRuleKey + identifier, indexPath ) ) )
4917 mSymbolLayers.insert( sl );
4922 visitSymbol( subSymbol, identifier, indexPath );
4931 if ( symbolEntity->symbol() )
4933 visitSymbol( symbolEntity->symbol(), leaf.
identifier, {} );
4939 QString mCurrentRuleKey;
4940 const QSet<QgsSymbolLayerId> &mSymbolLayerIds;
4941 QSet<const QgsSymbolLayer *> mSymbolLayers;
4944 SymbolLayerVisitor visitor( symbolLayerIds );
4945 renderer->
accept( &visitor );
4946 return visitor.mSymbolLayers;
4951 if ( !s || !context )
4961 size = markerSymbol->
size( *context );
4963 else if ( lineSymbol )
4965 size = lineSymbol->
width( *context );
4974 if ( minSize > 0 && size < minSize )
4978 else if ( maxSize > 0 && size > maxSize )
4996 else if ( lineSymbol )
5010 QMap<QString, QgsProperty>::const_iterator paramIt = propertiesMap.constBegin();
5011 for ( ; paramIt != propertiesMap.constEnd(); ++paramIt )
5013 properties.insert( paramIt.key(), paramIt.value().valueAsString( context ) );
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.
@ 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...
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.
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.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
QgsGeometry pointOnSurface() const
Returns a point guaranteed to lie on the surface of a geometry.
static QgsGeometry fromPolylineXY(const QgsPolylineXY &polyline)
Creates a new LineString geometry from a list of QgsPointXY points.
QgsPolygonXY asPolygon() const
Returns the contents of the geometry as a polygon.
QgsPolylineXY asPolyline() const
Returns the contents of the geometry as a polyline.
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
Qgis::GeometryOperationResult addRing(const QVector< QgsPointXY > &ring)
Adds a new ring to this geometry.
QgsMultiPolylineXY asMultiPolyline() const
Returns the contents of the geometry as a multi-linestring.
static QgsGeometry fromPolygonXY(const QgsPolygonXY &polygon)
Creates a new geometry from a QgsPolygonXY.
QgsGeometry buffer(double distance, int segments) const
Returns a buffer region around this geometry having the given width and with a specified number of se...
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...
@ 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...
QgsUnitTypes::RenderUnit widthUnit() const
Returns the units for the line's width.
virtual double width() const
Returns the estimated width for the line symbol layer.
double offset() const
Returns the line's offset.
const QgsMapUnitScale & widthMapUnitScale() const
A line symbol type, for rendering LineString and MultiLineString geometries.
void setWidthUnit(QgsUnitTypes::RenderUnit unit)
Sets the width units for the whole symbol (including all symbol layers).
double width() const
Returns the estimated width for the whole symbol, which is the maximum width of all marker symbol lay...
void setWidth(double width)
Sets the width for the whole line symbol.
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)
Sets the size for the whole symbol.
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the size units for the whole symbol (including all symbol layers).
double size() const
Returns the estimated size for the whole symbol, which is the maximum size of all marker symbol layer...
static QDomElement expressionToOgcFilter(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr)
Creates OGC filter XML element.
static QDomElement expressionToOgcExpression(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr)
Creates an OGC expression 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.
QgsExpressionContext & expressionContext()
Gets the expression context.
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
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 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.
void setStrokeWidthUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the width of the fill's stroke.
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.
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 bool hasExternalGraphic(QDomElement &element)
static QString encodePenStyle(Qt::PenStyle style)
static bool needMarkerLine(QDomElement &element)
static QVector< qreal > decodeSldRealVector(const QString &s)
static bool needLinePatternFill(QDomElement &element)
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 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 double rescaleUom(double size, QgsUnitTypes::RenderUnit unit, const QVariantMap &props)
Rescales the given size based on the uomScale found in the props, if any is found,...
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 QString encodeSldUom(QgsUnitTypes::RenderUnit unit, double *scaleFactor)
Encodes a render unit into an SLD unit of measure string.
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
static QSizeF toSize(const QVariant &value, bool *ok=nullptr)
Converts a value to a size.
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 QgsUnitTypes::RenderUnit decodeSldUom(const QString &str, double *scaleFactor=nullptr)
Decodes a SLD unit of measure string to a render unit.
static QgsStringMap getSvgParameterList(QDomElement &element)
static bool needSvgFill(QDomElement &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 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 QSet< const QgsSymbolLayer * > toSymbolLayerPointers(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 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 QgsSymbol * restrictedSizeSymbol(const QgsSymbol *s, double minSize, double maxSize, QgsRenderContext *context, double &width, double &height)
Creates a new symbol with size restricted to min/max size if original size is out of min/max range.
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 QString fieldOrExpressionFromExpression(QgsExpression *expression)
Returns a field name if the whole expression is just a name of the field .
static bool createSymbolLayerListFromSld(QDomElement &element, QgsWkbTypes::GeometryType geomType, QList< QgsSymbolLayer * > &layers)
Creates a symbol layer list from a DOM element.
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 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 QPicture symbolLayerPreviewPicture(const QgsSymbolLayer *layer, QgsUnitTypes::RenderUnit units, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::SymbolType parentSymbolType=Qgis::SymbolType::Hybrid)
Draws a symbol layer preview to a QPicture.
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 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 double estimateMaxSymbolBleed(QgsSymbol *symbol, const QgsRenderContext &context)
Returns the maximum estimated bleed for the symbol.
static void wellKnownMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &name, const QColor &color, const QColor &strokeColor, Qt::PenStyle strokeStyle, double strokeWidth=-1, double size=-1)
static QString symbolProperties(QgsSymbol *symbol)
Returns a string representing the symbol.
static bool geometryFromSldElement(QDomElement &element, QString &geomFunc)
static QString encodeScaleMethod(Qgis::ScaleMethod scaleMethod)
Encodes a symbol scale method to a string.
static void createOnlineResourceElement(QDomDocument &doc, QDomElement &element, const QString &path, const QString &format)
static Qt::PenStyle decodePenStyle(const QString &str)
static void createRotationElement(QDomDocument &doc, QDomElement &element, const QString &rotationFunc)
static Qgis::SymbolCoordinateReference decodeCoordinateReference(const QString &string, bool *ok=nullptr)
Decodes a string representing a symbol coordinate reference mode.
static QgsSymbolMap loadSymbols(QDomElement &element, const QgsReadWriteContext &context)
Reads a collection of symbols from XML and returns them in a map. Caller is responsible for deleting ...
static QString encodePoint(QPointF point)
Encodes a QPointF to a string.
static void labelTextToSld(QDomDocument &doc, QDomElement &element, const QString &label, const QFont &font, const QColor &color=QColor(), double size=-1)
static QgsSymbolLayer * createMarkerLayerFromSld(QDomElement &element)
static QDomElement saveSymbols(QgsSymbolMap &symbols, const QString &tagName, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a collection of symbols to XML with specified tagName for the top-level element.
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
static QgsStringMap getVendorOptionList(QDomElement &element)
static 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 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 QIcon symbolLayerPreviewIcon(const QgsSymbolLayer *layer, QgsUnitTypes::RenderUnit u, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::SymbolType parentSymbolType=Qgis::SymbolType::Hybrid)
Draws a symbol layer preview to an icon.
static QString encodeRealVector(const QVector< qreal > &v)
Property
Data definable properties.
virtual bool setSubSymbol(QgsSymbol *symbol)
Sets layer's subsymbol. takes ownership of the passed symbol.
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 QgsSymbolLayer * clone() const =0
Shall be reimplemented by subclasses to create a deep copy of the instance.
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.
virtual void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the layer.
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(QgsWkbTypes::GeometryType type)
Sets the geometry type for the original feature geometry being rendered.
Abstract base class for all rendered symbols.
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
void setOutputUnit(QgsUnitTypes::RenderUnit unit)
Sets the units to use for sizes and widths within the symbol.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol property definitions.
Qgis::SymbolFlags flags() const
Returns flags for the symbol.
qreal opacity() const
Returns the opacity for the symbol.
bool clipFeaturesToExtent() const
Returns whether features drawn by the symbol will be clipped to the render context's extent.
void setFlags(Qgis::SymbolFlags flags)
Sets flags for the symbol.
bool hasDataDefinedProperties() const
Returns whether the symbol utilizes any data defined properties.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol's property collection, used for data defined overrides.
void setOpacity(qreal opacity)
Sets the opacity for the symbol.
void setMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the 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.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
bool forceRHR() const
Returns true if polygon features drawn by the symbol will be reoriented to follow the standard right-...
void setClipFeaturesToExtent(bool clipFeaturesToExtent)
Sets whether features drawn by the symbol should be clipped to the render context's extent.
void setForceRHR(bool force)
Sets whether polygon features drawn by the symbol should be reoriented to follow the standard right-h...
static Q_INVOKABLE QgsUnitTypes::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
RenderUnit
Rendering size units.
@ RenderUnknownUnit
Mixed or unknown units.
@ RenderMetersInMapUnits
Meters value as Map units.
@ RenderPercentage
Percentage of another measurement (e.g., canvas size, feature size)
@ RenderPoints
Points (e.g., for font sizes)
@ RenderMillimeters
Millimeters.
@ RenderMapUnits
Map units.
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
static Type flatType(Type 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, QgsWkbTypes::GeometryType geometryType)
calculate geometry shifted by a specified distance
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.