48 #include <QDomDocument>
50 #include <QDomElement>
58 #include <QRegularExpression>
60 #define POINTS_TO_MM 2.83464567
64 return QStringLiteral(
"%1,%2,%3,%4" ).arg( color.red() ).arg( color.green() ).arg( color.blue() ).arg( color.alpha() );
69 const QStringList lst =
str.split(
',' );
70 if ( lst.count() < 3 )
74 int red, green, blue, alpha;
76 green = lst[1].toInt();
77 blue = lst[2].toInt();
79 if ( lst.count() > 3 )
81 alpha = lst[3].toInt();
83 return QColor( red, green, blue, alpha );
88 return QString::number( alpha / 255.0,
'g', 2 );
94 double alpha =
str.toDouble( &ok );
95 if ( !ok || alpha > 1 )
106 case QFont::StyleNormal:
107 return QStringLiteral(
"normal" );
108 case QFont::StyleItalic:
109 return QStringLiteral(
"italic" );
110 case QFont::StyleOblique:
111 return QStringLiteral(
"oblique" );
119 if (
str == QLatin1String(
"normal" ) )
return QFont::StyleNormal;
120 if (
str == QLatin1String(
"italic" ) )
return QFont::StyleItalic;
121 if (
str == QLatin1String(
"oblique" ) )
return QFont::StyleOblique;
122 return QFont::StyleNormal;
127 if ( weight == 50 )
return QStringLiteral(
"normal" );
128 if ( weight == 75 )
return QStringLiteral(
"bold" );
132 if ( weight < 0 )
return QStringLiteral(
"100" );
133 if ( weight > 99 )
return QStringLiteral(
"900" );
134 return QString::number( weight * 800 / 99 + 100 );
140 const int weight =
str.toInt( &ok );
142 return static_cast< int >( QFont::Normal );
146 if ( weight > 900 )
return 99;
147 if ( weight < 100 )
return 0;
148 return ( weight - 100 ) * 99 / 800;
156 return QStringLiteral(
"no" );
158 return QStringLiteral(
"solid" );
160 return QStringLiteral(
"dash" );
162 return QStringLiteral(
"dot" );
163 case Qt::DashDotLine:
164 return QStringLiteral(
"dash dot" );
165 case Qt::DashDotDotLine:
166 return QStringLiteral(
"dash dot dot" );
168 return QStringLiteral(
"???" );
174 if (
str == QLatin1String(
"no" ) )
return Qt::NoPen;
175 if (
str == QLatin1String(
"solid" ) )
return Qt::SolidLine;
176 if (
str == QLatin1String(
"dash" ) )
return Qt::DashLine;
177 if (
str == QLatin1String(
"dot" ) )
return Qt::DotLine;
178 if (
str == QLatin1String(
"dash dot" ) )
return Qt::DashDotLine;
179 if (
str == QLatin1String(
"dash dot dot" ) )
return Qt::DashDotDotLine;
180 return Qt::SolidLine;
188 return QStringLiteral(
"bevel" );
190 return QStringLiteral(
"miter" );
192 return QStringLiteral(
"round" );
194 return QStringLiteral(
"???" );
200 const QString cleaned =
str.toLower().trimmed();
201 if ( cleaned == QLatin1String(
"bevel" ) )
202 return Qt::BevelJoin;
203 if ( cleaned == QLatin1String(
"miter" ) )
204 return Qt::MiterJoin;
205 if ( cleaned == QLatin1String(
"round" ) )
206 return Qt::RoundJoin;
207 return Qt::BevelJoin;
215 return QStringLiteral(
"bevel" );
217 return QStringLiteral(
"mitre" );
219 return QStringLiteral(
"round" );
227 if (
str == QLatin1String(
"bevel" ) )
return Qt::BevelJoin;
228 if (
str == QLatin1String(
"mitre" ) )
return Qt::MiterJoin;
229 if (
str == QLatin1String(
"round" ) )
return Qt::RoundJoin;
230 return Qt::BevelJoin;
238 return QStringLiteral(
"square" );
240 return QStringLiteral(
"flat" );
242 return QStringLiteral(
"round" );
244 return QStringLiteral(
"???" );
250 if (
str == QLatin1String(
"square" ) )
return Qt::SquareCap;
251 if (
str == QLatin1String(
"flat" ) )
return Qt::FlatCap;
252 if (
str == QLatin1String(
"round" ) )
return Qt::RoundCap;
253 return Qt::SquareCap;
261 return QStringLiteral(
"square" );
263 return QStringLiteral(
"butt" );
265 return QStringLiteral(
"round" );
273 if (
str == QLatin1String(
"square" ) )
return Qt::SquareCap;
274 if (
str == QLatin1String(
"butt" ) )
return Qt::FlatCap;
275 if (
str == QLatin1String(
"round" ) )
return Qt::RoundCap;
276 return Qt::SquareCap;
283 case Qt::SolidPattern :
284 return QStringLiteral(
"solid" );
285 case Qt::HorPattern :
286 return QStringLiteral(
"horizontal" );
287 case Qt::VerPattern :
288 return QStringLiteral(
"vertical" );
289 case Qt::CrossPattern :
290 return QStringLiteral(
"cross" );
291 case Qt::BDiagPattern :
292 return QStringLiteral(
"b_diagonal" );
293 case Qt::FDiagPattern :
294 return QStringLiteral(
"f_diagonal" );
295 case Qt::DiagCrossPattern :
296 return QStringLiteral(
"diagonal_x" );
297 case Qt::Dense1Pattern :
298 return QStringLiteral(
"dense1" );
299 case Qt::Dense2Pattern :
300 return QStringLiteral(
"dense2" );
301 case Qt::Dense3Pattern :
302 return QStringLiteral(
"dense3" );
303 case Qt::Dense4Pattern :
304 return QStringLiteral(
"dense4" );
305 case Qt::Dense5Pattern :
306 return QStringLiteral(
"dense5" );
307 case Qt::Dense6Pattern :
308 return QStringLiteral(
"dense6" );
309 case Qt::Dense7Pattern :
310 return QStringLiteral(
"dense7" );
312 return QStringLiteral(
"no" );
314 return QStringLiteral(
"???" );
320 if (
str == QLatin1String(
"solid" ) )
return Qt::SolidPattern;
321 if (
str == QLatin1String(
"horizontal" ) )
return Qt::HorPattern;
322 if (
str == QLatin1String(
"vertical" ) )
return Qt::VerPattern;
323 if (
str == QLatin1String(
"cross" ) )
return Qt::CrossPattern;
324 if (
str == QLatin1String(
"b_diagonal" ) )
return Qt::BDiagPattern;
325 if (
str == QLatin1String(
"f_diagonal" ) )
return Qt::FDiagPattern;
326 if (
str == QLatin1String(
"diagonal_x" ) )
return Qt::DiagCrossPattern;
327 if (
str == QLatin1String(
"dense1" ) )
return Qt::Dense1Pattern;
328 if (
str == QLatin1String(
"dense2" ) )
return Qt::Dense2Pattern;
329 if (
str == QLatin1String(
"dense3" ) )
return Qt::Dense3Pattern;
330 if (
str == QLatin1String(
"dense4" ) )
return Qt::Dense4Pattern;
331 if (
str == QLatin1String(
"dense5" ) )
return Qt::Dense5Pattern;
332 if (
str == QLatin1String(
"dense6" ) )
return Qt::Dense6Pattern;
333 if (
str == QLatin1String(
"dense7" ) )
return Qt::Dense7Pattern;
334 if (
str == QLatin1String(
"no" ) )
return Qt::NoBrush;
335 return Qt::SolidPattern;
342 case Qt::CrossPattern:
343 return QStringLiteral(
"cross" );
344 case Qt::DiagCrossPattern:
345 return QStringLiteral(
"x" );
352 return QStringLiteral(
"horline" );
354 return QStringLiteral(
"line" );
355 case Qt::BDiagPattern:
356 return QStringLiteral(
"slash" );
357 case Qt::FDiagPattern:
358 return QStringLiteral(
"backslash" );
361 case Qt::Dense1Pattern:
362 case Qt::Dense2Pattern:
363 case Qt::Dense3Pattern:
364 case Qt::Dense4Pattern:
365 case Qt::Dense5Pattern:
366 case Qt::Dense6Pattern:
367 case Qt::Dense7Pattern:
377 if (
str == QLatin1String(
"horline" ) )
return Qt::HorPattern;
378 if (
str == QLatin1String(
"line" ) )
return Qt::VerPattern;
379 if (
str == QLatin1String(
"cross" ) )
return Qt::CrossPattern;
380 if (
str == QLatin1String(
"slash" ) )
return Qt::BDiagPattern;
381 if (
str == QLatin1String(
"backshash" ) )
return Qt::FDiagPattern;
382 if (
str == QLatin1String(
"x" ) )
return Qt::DiagCrossPattern;
384 if (
str.startsWith( QLatin1String(
"brush://" ) ) )
396 const QString s = value.toString().toLower().trimmed();
397 if ( s == QLatin1String(
"single" ) )
399 else if ( s == QLatin1String(
"reversed" ) )
401 else if ( s == QLatin1String(
"double" ) )
403 else if ( value.toInt() == 1 )
405 else if ( value.toInt() == 2 )
407 else if ( value.toInt( &intOk ) == 0 && intOk )
421 const QString s = value.toString().toLower().trimmed();
422 if ( s == QLatin1String(
"plain" ) )
424 else if ( s == QLatin1String(
"lefthalf" ) )
426 else if ( s == QLatin1String(
"righthalf" ) )
428 else if ( value.toInt() == 1 )
430 else if ( value.toInt() == 2 )
432 else if ( value.toInt( &intOk ) == 0 && intOk )
447 QStringList lst =
str.split(
',' );
448 if ( lst.count() != 2 )
449 return QPointF( 0, 0 );
450 return QPointF( lst[0].toDouble(), lst[1].toDouble() );
458 if ( value.isNull() )
461 if ( value.type() == QVariant::List )
463 const QVariantList list = value.toList();
464 if ( list.size() != 2 )
468 bool convertOk =
false;
469 const double x = list.at( 0 ).toDouble( &convertOk );
472 const double y = list.at( 1 ).toDouble( &convertOk );
477 return QPointF( x, y );
485 const QStringList list = value.toString().trimmed().split(
',' );
486 if ( list.count() != 2 )
488 bool convertOk =
false;
489 const double x = list.at( 0 ).toDouble( &convertOk );
492 const double y = list.at( 1 ).toDouble( &convertOk );
497 return QPointF( x, y );
511 QStringList lst =
string.split(
',' );
512 if ( lst.count() != 2 )
513 return QSizeF( 0, 0 );
514 return QSizeF( lst[0].toDouble(), lst[1].toDouble() );
522 if ( value.isNull() )
525 if ( value.type() == QVariant::List )
527 const QVariantList list = value.toList();
528 if ( list.size() != 2 )
532 bool convertOk =
false;
533 const double x = list.at( 0 ).toDouble( &convertOk );
536 const double y = list.at( 1 ).toDouble( &convertOk );
541 return QSizeF( x, y );
549 const QStringList list = value.toString().trimmed().split(
',' );
550 if ( list.count() != 2 )
552 bool convertOk =
false;
553 const double x = list.at( 0 ).toDouble( &convertOk );
556 const double y = list.at( 1 ).toDouble( &convertOk );
561 return QSizeF( x, y );
582 if (
str.startsWith( QLatin1String(
"3x:" ) ) )
585 const QString chopped =
str.mid( 3 );
586 lst = chopped.split(
',' );
590 lst =
str.split(
',' );
592 if ( lst.count() < 2 )
595 double minScale = lst[0].toDouble();
597 minScale = minScale != 0 ? 1.0 / minScale : 0;
598 double maxScale = lst[1].toDouble();
600 maxScale = maxScale != 0 ? 1.0 / maxScale : 0;
602 if ( lst.count() < 6 )
622 *scaleFactor = 0.001;
623 return QStringLiteral(
"http://www.opengeospatial.org/se/units/metre" );
630 *scaleFactor = 1 / 0.28;
639 if (
str == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
642 *scaleFactor = 1000.0;
645 else if (
str == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
648 *scaleFactor = 304.8;
651 else if (
str == QLatin1String(
"http://www.opengeospatial.org/se/units/pixel" ) )
661 *scaleFactor = 1 / 0.00028;
667 QString vectorString;
668 QVector<qreal>::const_iterator it = v.constBegin();
669 for ( ; it != v.constEnd(); ++it )
671 if ( it != v.constBegin() )
673 vectorString.append(
';' );
675 vectorString.append( QString::number( *it ) );
682 QVector<qreal> resultVector;
684 const QStringList realList = s.split(
';' );
685 QStringList::const_iterator it = realList.constBegin();
686 for ( ; it != realList.constEnd(); ++it )
688 resultVector.append( it->toDouble() );
696 QString vectorString;
697 QVector<qreal>::const_iterator it = v.constBegin();
698 for ( ; it != v.constEnd(); ++it )
700 if ( it != v.constBegin() )
702 vectorString.append(
' ' );
704 vectorString.append( QString::number( *it ) );
711 QVector<qreal> resultVector;
713 const QStringList realList = s.split(
' ' );
714 QStringList::const_iterator it = realList.constBegin();
715 for ( ; it != realList.constEnd(); ++it )
717 resultVector.append( it->toDouble() );
725 QString encodedValue;
727 switch ( scaleMethod )
730 encodedValue = QStringLiteral(
"diameter" );
733 encodedValue = QStringLiteral(
"area" );
743 if (
str == QLatin1String(
"diameter" ) )
757 if ( s.compare( QLatin1String(
"Lighten" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Lighten;
758 if ( s.compare( QLatin1String(
"Screen" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Screen;
759 if ( s.compare( QLatin1String(
"Dodge" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorDodge;
760 if ( s.compare( QLatin1String(
"Addition" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Plus;
761 if ( s.compare( QLatin1String(
"Darken" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Darken;
762 if ( s.compare( QLatin1String(
"Multiply" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Multiply;
763 if ( s.compare( QLatin1String(
"Burn" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorBurn;
764 if ( s.compare( QLatin1String(
"Overlay" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Overlay;
765 if ( s.compare( QLatin1String(
"SoftLight" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_SoftLight;
766 if ( s.compare( QLatin1String(
"HardLight" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_HardLight;
767 if ( s.compare( QLatin1String(
"Difference" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Difference;
768 if ( s.compare( QLatin1String(
"Subtract" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Exclusion;
769 return QPainter::CompositionMode_SourceOver;
774 return QIcon(
symbolPreviewPixmap( symbol, size, padding,
nullptr,
false,
nullptr, shape ) );
780 QPixmap pixmap( size );
781 pixmap.fill( Qt::transparent );
783 painter.begin( &pixmap );
787 painter.setRenderHint( QPainter::Antialiasing );
796 size.setWidth( size.rwidth() - ( padding * 2 ) );
797 size.setHeight( size.rheight() - ( padding * 2 ) );
798 painter.translate( padding, padding );
808 std::unique_ptr<QgsSymbol> symbol_noDD( symbol->
clone( ) );
810 for (
const auto &layer : layers )
812 for (
int i = 0; i < layer->dataDefinedProperties().count(); ++i )
814 QgsProperty &prop = layer->dataDefinedProperties().property( i );
820 symbol_noDD->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape );
824 std::unique_ptr<QgsSymbol> symbolClone( symbol->
clone( ) );
825 symbolClone->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape );
839 maxBleed = layerMaxBleed > maxBleed ? layerMaxBleed : maxBleed;
849 painter.begin( &picture );
850 painter.setRenderHint( QPainter::Antialiasing );
854 QgsSymbolRenderContext symbolContext( renderContext, units, 1.0,
false, Qgis::SymbolRenderHints(),
nullptr );
856 switch ( parentSymbolType )
871 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
872 layerClone->drawPreviewIcon( symbolContext, size );
879 QPixmap pixmap( size );
880 pixmap.fill( Qt::transparent );
882 painter.begin( &pixmap );
883 painter.setRenderHint( QPainter::Antialiasing );
893 switch ( parentSymbolType )
908 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
909 layerClone->drawPreviewIcon( symbolContext, size );
911 return QIcon( pixmap );
921 QPixmap pixmap( size );
922 pixmap.fill( Qt::transparent );
925 painter.begin( &pixmap );
928 if ( drawTransparentBackground )
929 drawStippledBackground( &painter, QRect( padding, padding, size.width() - padding * 2, size.height() - padding * 2 ) );
937 for (
int i = 0; i < size.width(); i++ )
939 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.width() ) );
940 painter.setPen( pen );
941 const int x = flipDirection ? size.width() - i - 1 : i;
942 painter.drawLine( x, 0 + padding, x, size.height() - 1 - padding );
949 for (
int i = 0; i < size.height(); i++ )
951 const QPen pen( ramp->
color(
static_cast< double >( i ) / size.height() ) );
952 painter.setPen( pen );
953 const int y = flipDirection ? size.height() - i - 1 : i;
954 painter.drawLine( 0 + padding, y, size.width() - 1 - padding, y );
967 uchar pixDataRGB[] = { 255, 255, 255, 255,
972 const QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
974 const int width = ( rect.width() < rect.height() ) ?
975 rect.width() / 2.5 : rect.height() / 2.5;
976 const QPixmap pix = QPixmap::fromImage( img.scaled( width, width ) );
979 brush.setTexture( pix );
980 painter->fillRect( rect, brush );
985 const qreal s = ( markerSize - 1 ) / 2.0;
990 p.setPen( QColor( 50, 100, 120, 200 ) );
991 p.setBrush( QColor( 200, 200, 210, 120 ) );
992 p.drawEllipse( x - s, y - s, s * 2, s * 2 );
995 p.setPen( QColor( 255, 0, 0 ) );
996 p.drawLine( x - s, y + s, x + s, y - s );
997 p.drawLine( x - s, y - s, x + s, y + s );
1004 #include <QPolygonF>
1009 static QPolygonF makeOffsetGeometry(
const QgsPolylineXY &polyline )
1011 int i, pointCount = polyline.count();
1013 QPolygonF resultLine;
1014 resultLine.resize( pointCount );
1018 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1019 resultLine[i] = QPointF( tempPtr->
x(), tempPtr->
y() );
1023 static QList<QPolygonF> makeOffsetGeometry(
const QgsPolygonXY &polygon )
1025 QList<QPolygonF> resultGeom;
1026 resultGeom.reserve( polygon.size() );
1027 for (
int ring = 0; ring < polygon.size(); ++ring )
1028 resultGeom.append( makeOffsetGeometry( polygon[ ring ] ) );
1034 QList<QPolygonF> resultLine;
1036 if ( polyline.count() < 2 )
1038 resultLine.append( polyline );
1042 unsigned int i, pointCount = polyline.count();
1045 QPointF *tempPtr = polyline.data();
1046 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1047 tempPolyline[i] =
QgsPointXY( tempPtr->rx(), tempPtr->ry() );
1050 if ( !tempGeometry.
isNull() )
1052 const int quadSegments = 0;
1053 const double miterLimit = 2.0;
1056 offsetGeom = tempGeometry.
buffer( -dist, quadSegments, Qgis::EndCapStyle::Flat,
1057 Qgis::JoinStyle::Miter, miterLimit );
1059 offsetGeom = tempGeometry.
offsetCurve( dist, quadSegments, Qgis::JoinStyle::Miter, miterLimit );
1061 if ( !offsetGeom.
isNull() )
1063 tempGeometry = offsetGeom;
1068 resultLine.append( makeOffsetGeometry( line ) );
1073 resultLine.append( makeOffsetGeometry( tempGeometry.
asPolygon() ) );
1079 resultLine.reserve( tempMPolyline.count() );
1080 for (
int part = 0; part < tempMPolyline.count(); ++part )
1082 resultLine.append( makeOffsetGeometry( tempMPolyline[ part ] ) );
1089 resultLine.reserve( tempMPolygon.count() );
1090 for (
int part = 0; part < tempMPolygon.count(); ++part )
1092 resultLine.append( makeOffsetGeometry( tempMPolygon[ part ] ) );
1100 resultLine.append( polyline );
1110 QDomNode layerNode = element.firstChild();
1112 while ( !layerNode.isNull() )
1114 QDomElement e = layerNode.toElement();
1115 if ( !e.isNull() && e.tagName() != QLatin1String(
"data_defined_properties" ) )
1117 if ( e.tagName() != QLatin1String(
"layer" ) )
1128 const QDomElement s = e.firstChildElement( QStringLiteral(
"symbol" ) );
1135 QgsDebugMsg(
"symbol layer refused subsymbol: " + s.attribute(
"name" ) );
1138 layers.append( layer );
1142 layerNode = layerNode.nextSibling();
1145 if ( layers.isEmpty() )
1147 QgsDebugMsg( QStringLiteral(
"no layers for symbol" ) );
1151 const QString symbolType = element.attribute( QStringLiteral(
"type" ) );
1154 if ( symbolType == QLatin1String(
"line" ) )
1156 else if ( symbolType == QLatin1String(
"fill" ) )
1158 else if ( symbolType == QLatin1String(
"marker" ) )
1162 QgsDebugMsg(
"unknown symbol type " + symbolType );
1166 if ( element.hasAttribute( QStringLiteral(
"outputUnit" ) ) )
1170 if ( element.hasAttribute( ( QStringLiteral(
"mapUnitScale" ) ) ) )
1173 const double oldMin = element.attribute( QStringLiteral(
"mapUnitMinScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1174 mapUnitScale.
minScale = oldMin != 0 ? 1.0 / oldMin : 0;
1175 const double oldMax = element.attribute( QStringLiteral(
"mapUnitMaxScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1176 mapUnitScale.
maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
1179 symbol->
setOpacity( element.attribute( QStringLiteral(
"alpha" ), QStringLiteral(
"1.0" ) ).toDouble() );
1180 symbol->
setClipFeaturesToExtent( element.attribute( QStringLiteral(
"clip_to_extent" ), QStringLiteral(
"1" ) ).toInt() );
1181 symbol->
setForceRHR( element.attribute( QStringLiteral(
"force_rhr" ), QStringLiteral(
"0" ) ).toInt() );
1182 Qgis::SymbolFlags flags;
1183 if ( element.attribute( QStringLiteral(
"renderer_should_use_levels" ), QStringLiteral(
"0" ) ).toInt() )
1187 const QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1188 if ( !ddProps.isNull() )
1198 const QString layerClass = element.attribute( QStringLiteral(
"class" ) );
1199 const bool locked = element.attribute( QStringLiteral(
"locked" ) ).toInt();
1200 const bool enabled = element.attribute( QStringLiteral(
"enabled" ), QStringLiteral(
"1" ) ).toInt();
1201 const int pass = element.attribute( QStringLiteral(
"pass" ) ).toInt();
1220 const QDomElement effectElem = element.firstChildElement( QStringLiteral(
"effect" ) );
1221 if ( !effectElem.isNull() )
1229 const QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1230 if ( !ddProps.isNull() )
1237 const QSet< int > oldKeys = prevProperties.
propertyKeys();
1238 for (
int key : oldKeys )
1259 return QStringLiteral(
"line" );
1261 return QStringLiteral(
"marker" );
1263 return QStringLiteral(
"fill" );
1272 QDomElement symEl = doc.createElement( QStringLiteral(
"symbol" ) );
1273 symEl.setAttribute( QStringLiteral(
"type" ), _nameForSymbolType( symbol->
type() ) );
1274 symEl.setAttribute( QStringLiteral(
"name" ), name );
1275 symEl.setAttribute( QStringLiteral(
"alpha" ), QString::number( symbol->
opacity() ) );
1276 symEl.setAttribute( QStringLiteral(
"clip_to_extent" ), symbol->
clipFeaturesToExtent() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1277 symEl.setAttribute( QStringLiteral(
"force_rhr" ), symbol->
forceRHR() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1279 symEl.setAttribute( QStringLiteral(
"renderer_should_use_levels" ), QStringLiteral(
"1" ) );
1283 QDomElement ddProps = doc.createElement( QStringLiteral(
"data_defined_properties" ) );
1285 symEl.appendChild( ddProps );
1291 QDomElement layerEl = doc.createElement( QStringLiteral(
"layer" ) );
1292 layerEl.setAttribute( QStringLiteral(
"class" ), layer->
layerType() );
1293 layerEl.setAttribute( QStringLiteral(
"enabled" ), layer->
enabled() );
1294 layerEl.setAttribute( QStringLiteral(
"locked" ), layer->
isLocked() );
1295 layerEl.setAttribute( QStringLiteral(
"pass" ), layer->
renderingPass() );
1307 QDomElement ddProps = doc.createElement( QStringLiteral(
"data_defined_properties" ) );
1309 layerEl.appendChild( ddProps );
1313 const QString subname = QStringLiteral(
"@%1@%2" ).arg( name ).arg( i );
1314 const QDomElement subEl =
saveSymbol( subname, subSymbol, doc, context );
1315 layerEl.appendChild( subEl );
1317 symEl.appendChild( layerEl );
1325 QDomDocument doc( QStringLiteral(
"qgis-symbol-definition" ) );
1328 QTextStream stream( &props );
1329 symbolElem.save( stream, -1 );
1335 QList<QgsSymbolLayer *> &layers )
1339 if ( element.isNull() )
1344 const QString symbolizerName = element.localName();
1346 if ( symbolizerName == QLatin1String(
"PointSymbolizer" ) )
1349 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1350 if ( graphicElem.isNull() )
1352 QgsDebugMsg( QStringLiteral(
"Graphic element not found in PointSymbolizer" ) );
1388 if ( symbolizerName == QLatin1String(
"LineSymbolizer" ) )
1391 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1392 if ( strokeElem.isNull() )
1394 QgsDebugMsg( QStringLiteral(
"Stroke element not found in LineSymbolizer" ) );
1424 if ( symbolizerName == QLatin1String(
"PolygonSymbolizer" ) )
1427 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1428 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1429 if ( fillElem.isNull() && strokeElem.isNull() )
1431 QgsDebugMsg( QStringLiteral(
"neither Fill nor Stroke element not found in PolygonSymbolizer" ) );
1449 if ( l->
layerType() == QLatin1String(
"SimpleFill" ) || l->
layerType() == QLatin1String(
"SVGFill" ) )
1485 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1486 if ( fillElem.isNull() )
1488 QgsDebugMsg( QStringLiteral(
"Fill element not found" ) );
1508 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1509 if ( strokeElem.isNull() )
1511 QgsDebugMsg( QStringLiteral(
"Stroke element not found" ) );
1527 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1528 if ( graphicElem.isNull() )
1530 QgsDebugMsg( QStringLiteral(
"Graphic element not found" ) );
1550 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1551 if ( graphicElem.isNull() )
1554 const QDomElement externalGraphicElem = graphicElem.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
1555 if ( externalGraphicElem.isNull() )
1559 const QDomElement formatElem = externalGraphicElem.firstChildElement( QStringLiteral(
"Format" ) );
1560 if ( formatElem.isNull() )
1563 const QString format = formatElem.firstChild().nodeValue();
1564 if ( format != QLatin1String(
"image/svg+xml" ) )
1566 QgsDebugMsg(
"unsupported External Graphic format found: " + format );
1571 const QDomElement onlineResourceElem = externalGraphicElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1572 const QDomElement inlineContentElem = externalGraphicElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1573 if ( !onlineResourceElem.isNull() )
1578 else if ( !inlineContentElem.isNull() )
1591 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1592 if ( graphicElem.isNull() )
1595 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1596 if ( markElem.isNull() )
1599 const QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
1600 return !wellKnownNameElem.isNull();
1606 const QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1607 if ( graphicElem.isNull() )
1610 const QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1611 if ( markElem.isNull() )
1615 const QDomElement formatElem = markElem.firstChildElement( QStringLiteral(
"Format" ) );
1616 if ( formatElem.isNull() )
1619 const QString format = formatElem.firstChild().nodeValue();
1620 if ( format != QLatin1String(
"ttf" ) )
1622 QgsDebugMsg(
"unsupported Graphic Mark format found: " + format );
1627 const QDomElement onlineResourceElem = markElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1628 const QDomElement inlineContentElem = markElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1629 if ( !onlineResourceElem.isNull() )
1632 const QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
1633 if ( !markIndexElem.isNull() )
1636 else if ( !inlineContentElem.isNull() )
1651 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1652 if ( graphicElem.isNull() )
1656 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
1658 if ( it.key() == QLatin1String(
"widthHeightFactor" ) )
1669 const QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1670 if ( strokeElem.isNull() )
1673 QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral(
"GraphicStroke" ) );
1674 if ( graphicStrokeElem.isNull() )
1682 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1683 if ( fillElem.isNull() )
1686 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1687 if ( graphicFillElem.isNull() )
1690 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1691 if ( graphicElem.isNull() )
1697 QColor fillColor, strokeColor;
1698 double size, strokeWidth;
1699 Qt::PenStyle strokeStyle;
1700 if ( !
wellKnownMarkerFromSld( graphicElem, name, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
1703 if ( name != QLatin1String(
"horline" ) )
1711 const double angle = angleFunc.toDouble( &ok );
1723 const QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1724 if ( fillElem.isNull() )
1727 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1728 if ( graphicFillElem.isNull() )
1748 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1749 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1753 bool validFill =
false, validStroke =
false;
1758 Qt::BrushStyle fillStyle;
1760 if (
fillFromSld( fillElem, fillStyle, fillColor ) )
1766 Qt::PenStyle strokeStyle;
1767 double strokeWidth = 1.0, dashOffset = 0.0;
1768 QVector<qreal> customDashPattern;
1770 if (
lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth,
1771 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
1774 if ( validFill || validStroke )
1777 map[QStringLiteral(
"name" )] = QStringLiteral(
"square" );
1778 map[QStringLiteral(
"color" )] =
encodeColor( validFill ? fillColor : Qt::transparent );
1779 map[QStringLiteral(
"color_border" )] =
encodeColor( validStroke ? strokeColor : Qt::transparent );
1780 map[QStringLiteral(
"size" )] = QString::number( 6 );
1781 map[QStringLiteral(
"angle" )] = QString::number( 0 );
1782 map[QStringLiteral(
"offset" )] =
encodePoint( QPointF( 0, 0 ) );
1789 bool validFill =
false, validStroke =
false;
1792 QString name, format;
1794 QColor fillColor, strokeColor;
1795 double strokeWidth = 1.0, size = 0.0,
angle = 0.0;
1799 const QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1800 if ( !graphicFillElem.isNull() )
1803 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1804 if ( !graphicElem.isNull() )
1810 const QDomElement graphicChildElem = graphicElem.firstChildElement();
1811 while ( !graphicChildElem.isNull() )
1813 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
1816 const QDomElement wellKnownNameElem = graphicChildElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
1817 if ( !wellKnownNameElem.isNull() )
1819 name = wellKnownNameElem.firstChild().nodeValue();
1825 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) || graphicChildElem.localName() == QLatin1String(
"Mark" ) )
1828 const QDomElement formatElem = graphicChildElem.firstChildElement( QStringLiteral(
"Format" ) );
1829 if ( formatElem.isNull() )
1832 format = formatElem.firstChild().nodeValue();
1836 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) && format != QLatin1String(
"image/svg+xml" ) )
1841 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format != QLatin1String(
"ttf" ) )
1845 const QDomElement onlineResourceElem = graphicChildElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1846 const QDomElement inlineContentElem = graphicChildElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1848 if ( !onlineResourceElem.isNull() )
1850 name = onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) );
1852 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format == QLatin1String(
"ttf" ) )
1855 if ( name.startsWith( QLatin1String(
"ttf://" ) ) )
1856 name = name.mid( 6 );
1859 const QDomElement markIndexElem = graphicChildElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
1860 if ( markIndexElem.isNull() )
1864 const int v = markIndexElem.firstChild().nodeValue().toInt( &ok );
1875 else if ( !inlineContentElem.isNull() )
1885 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
1887 name = QStringLiteral(
"square" );
1894 if ( found && graphicChildElem.localName() == QLatin1String(
"Mark" ) )
1901 Qt::BrushStyle markFillStyle;
1903 QDomElement markFillElem = graphicChildElem.firstChildElement( QStringLiteral(
"Fill" ) );
1904 if (
fillFromSld( markFillElem, markFillStyle, fillColor ) )
1909 Qt::PenStyle strokeStyle;
1910 double strokeWidth = 1.0, dashOffset = 0.0;
1911 QVector<qreal> customDashPattern;
1913 QDomElement markStrokeElem = graphicChildElem.firstChildElement( QStringLiteral(
"Stroke" ) );
1914 if (
lineFromSld( markStrokeElem, strokeStyle, strokeColor, strokeWidth,
1915 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
1922 const QDomElement opacityElem = graphicElem.firstChildElement( QStringLiteral(
"Opacity" ) );
1923 if ( !opacityElem.isNull() )
1924 fillColor.setAlpha(
decodeSldAlpha( opacityElem.firstChild().nodeValue() ) );
1926 const QDomElement sizeElem = graphicElem.firstChildElement( QStringLiteral(
"Size" ) );
1927 if ( !sizeElem.isNull() )
1930 const double v = sizeElem.firstChild().nodeValue().toDouble( &ok );
1939 const double v = angleFunc.toDouble( &ok );
1949 if ( validFill || validStroke )
1951 if ( format == QLatin1String(
"image/svg+xml" ) )
1954 map[QStringLiteral(
"name" )] = name;
1955 map[QStringLiteral(
"fill" )] = fillColor.name();
1956 map[QStringLiteral(
"outline" )] = strokeColor.name();
1957 map[QStringLiteral(
"outline-width" )] = QString::number( strokeWidth );
1959 map[QStringLiteral(
"size" )] = QString::number( size );
1961 map[QStringLiteral(
"angle" )] = QString::number(
angle );
1962 if ( !offset.isNull() )
1963 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
1966 else if ( format == QLatin1String(
"ttf" ) )
1969 map[QStringLiteral(
"font" )] = name;
1970 map[QStringLiteral(
"chr" )] = markIndex;
1971 map[QStringLiteral(
"color" )] =
encodeColor( validFill ? fillColor : Qt::transparent );
1973 map[QStringLiteral(
"size" )] = QString::number( size );
1975 map[QStringLiteral(
"angle" )] = QString::number(
angle );
1976 if ( !offset.isNull() )
1977 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
1983 if ( layers.isEmpty() )
1986 layerList << layers;
1993 QString patternName;
1994 switch ( brushStyle )
1999 case Qt::SolidPattern:
2000 if ( color.isValid() )
2003 if ( color.alpha() < 255 )
2008 case Qt::CrossPattern:
2009 case Qt::DiagCrossPattern:
2010 case Qt::HorPattern:
2011 case Qt::VerPattern:
2012 case Qt::BDiagPattern:
2013 case Qt::FDiagPattern:
2014 case Qt::Dense1Pattern:
2015 case Qt::Dense2Pattern:
2016 case Qt::Dense3Pattern:
2017 case Qt::Dense4Pattern:
2018 case Qt::Dense5Pattern:
2019 case Qt::Dense6Pattern:
2020 case Qt::Dense7Pattern:
2025 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( brushStyle ) ) );
2029 QDomElement graphicFillElem = doc.createElement( QStringLiteral(
"se:GraphicFill" ) );
2030 element.appendChild( graphicFillElem );
2032 QDomElement graphicElem = doc.createElement( QStringLiteral(
"se:Graphic" ) );
2033 graphicFillElem.appendChild( graphicElem );
2035 const QColor fillColor = patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
2036 const QColor strokeColor = !patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
2039 wellKnownMarkerToSld( doc, graphicElem, patternName, fillColor, strokeColor, Qt::SolidLine, -1, -1 );
2046 brushStyle = Qt::SolidPattern;
2047 color = QColor( 128, 128, 128 );
2049 if ( element.isNull() )
2051 brushStyle = Qt::NoBrush;
2056 const QDomElement graphicFillElem = element.firstChildElement( QStringLiteral(
"GraphicFill" ) );
2058 if ( graphicFillElem.isNull() )
2061 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2063 QgsDebugMsg( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ) );
2065 if ( it.key() == QLatin1String(
"fill" ) )
2066 color = QColor( it.value() );
2067 else if ( it.key() == QLatin1String(
"fill-opacity" ) )
2073 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
2074 if ( graphicElem.isNull() )
2077 QString patternName = QStringLiteral(
"square" );
2078 QColor fillColor, strokeColor;
2079 double strokeWidth, size;
2080 Qt::PenStyle strokeStyle;
2081 if ( !
wellKnownMarkerFromSld( graphicElem, patternName, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
2085 if ( brushStyle == Qt::NoBrush )
2088 const QColor
c = patternName.startsWith( QLatin1String(
"brush://" ) ) ? fillColor : strokeColor;
2097 Qt::PenStyle penStyle,
const QColor &color,
double width,
2098 const Qt::PenJoinStyle *penJoinStyle,
const Qt::PenCapStyle *penCapStyle,
2099 const QVector<qreal> *customDashPattern,
double dashOffset )
2101 QVector<qreal> dashPattern;
2102 const QVector<qreal> *pattern = &dashPattern;
2104 if ( penStyle == Qt::CustomDashLine && !customDashPattern )
2106 element.appendChild( doc.createComment( QStringLiteral(
"WARNING: Custom dash pattern required but not provided. Using default dash pattern." ) ) );
2107 penStyle = Qt::DashLine;
2119 dashPattern.push_back( 4.0 );
2120 dashPattern.push_back( 2.0 );
2123 dashPattern.push_back( 1.0 );
2124 dashPattern.push_back( 2.0 );
2126 case Qt::DashDotLine:
2127 dashPattern.push_back( 4.0 );
2128 dashPattern.push_back( 2.0 );
2129 dashPattern.push_back( 1.0 );
2130 dashPattern.push_back( 2.0 );
2132 case Qt::DashDotDotLine:
2133 dashPattern.push_back( 4.0 );
2134 dashPattern.push_back( 2.0 );
2135 dashPattern.push_back( 1.0 );
2136 dashPattern.push_back( 2.0 );
2137 dashPattern.push_back( 1.0 );
2138 dashPattern.push_back( 2.0 );
2141 case Qt::CustomDashLine:
2142 Q_ASSERT( customDashPattern );
2143 pattern = customDashPattern;
2147 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( penStyle ) ) );
2151 if ( color.isValid() )
2154 if ( color.alpha() < 255 )
2161 else if ( width == 0 )
2171 if ( !pattern->isEmpty() )
2181 Qt::PenStyle &penStyle, QColor &color,
double &width,
2182 Qt::PenJoinStyle *penJoinStyle, Qt::PenCapStyle *penCapStyle,
2183 QVector<qreal> *customDashPattern,
double *dashOffset )
2187 penStyle = Qt::SolidLine;
2188 color = QColor( 0, 0, 0 );
2191 *penJoinStyle = Qt::BevelJoin;
2193 *penCapStyle = Qt::SquareCap;
2194 if ( customDashPattern )
2195 customDashPattern->clear();
2199 if ( element.isNull() )
2201 penStyle = Qt::NoPen;
2207 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2209 QgsDebugMsg( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ) );
2211 if ( it.key() == QLatin1String(
"stroke" ) )
2213 color = QColor( it.value() );
2215 else if ( it.key() == QLatin1String(
"stroke-opacity" ) )
2219 else if ( it.key() == QLatin1String(
"stroke-width" ) )
2222 const double w = it.value().toDouble( &ok );
2226 else if ( it.key() == QLatin1String(
"stroke-linejoin" ) && penJoinStyle )
2230 else if ( it.key() == QLatin1String(
"stroke-linecap" ) && penCapStyle )
2234 else if ( it.key() == QLatin1String(
"stroke-dasharray" ) )
2237 if ( !dashPattern.isEmpty() )
2241 bool dashPatternFound =
false;
2243 if ( dashPattern.count() == 2 )
2245 if ( dashPattern.at( 0 ) == 4.0 &&
2246 dashPattern.at( 1 ) == 2.0 )
2248 penStyle = Qt::DashLine;
2249 dashPatternFound =
true;
2251 else if ( dashPattern.at( 0 ) == 1.0 &&
2252 dashPattern.at( 1 ) == 2.0 )
2254 penStyle = Qt::DotLine;
2255 dashPatternFound =
true;
2258 else if ( dashPattern.count() == 4 )
2260 if ( dashPattern.at( 0 ) == 4.0 &&
2261 dashPattern.at( 1 ) == 2.0 &&
2262 dashPattern.at( 2 ) == 1.0 &&
2263 dashPattern.at( 3 ) == 2.0 )
2265 penStyle = Qt::DashDotLine;
2266 dashPatternFound =
true;
2269 else if ( dashPattern.count() == 6 )
2271 if ( dashPattern.at( 0 ) == 4.0 &&
2272 dashPattern.at( 1 ) == 2.0 &&
2273 dashPattern.at( 2 ) == 1.0 &&
2274 dashPattern.at( 3 ) == 2.0 &&
2275 dashPattern.at( 4 ) == 1.0 &&
2276 dashPattern.at( 5 ) == 2.0 )
2278 penStyle = Qt::DashDotDotLine;
2279 dashPatternFound =
true;
2284 if ( !dashPatternFound )
2286 if ( customDashPattern )
2288 penStyle = Qt::CustomDashLine;
2289 *customDashPattern = dashPattern;
2293 QgsDebugMsg( QStringLiteral(
"custom dash pattern required but not provided. Using default dash pattern." ) );
2294 penStyle = Qt::DashLine;
2299 else if ( it.key() == QLatin1String(
"stroke-dashoffset" ) && dashOffset )
2302 const double d = it.value().toDouble( &ok );
2312 const QString &path,
const QString &mime,
2313 const QColor &color,
double size )
2315 QDomElement externalGraphicElem = doc.createElement( QStringLiteral(
"se:ExternalGraphic" ) );
2316 element.appendChild( externalGraphicElem );
2325 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2327 element.appendChild( sizeElem );
2332 const QString &path,
const QColor &fillColor,
double size,
const QColor &strokeColor,
double strokeWidth )
2339 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Parametric SVG" ) ) );
2340 const QString parametricPath =
getSvgParametricPath( path, fillColor, strokeColor, strokeWidth );
2343 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Plain SVG fallback, no parameters" ) ) );
2346 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Well known marker fallback" ) ) );
2352 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2354 graphicElem.appendChild( sizeElem );
2362 if ( fillColor.isValid() )
2364 url.addQueryItem( QStringLiteral(
"fill" ), fillColor.name() );
2365 url.addQueryItem( QStringLiteral(
"fill-opacity" ),
encodeSldAlpha( fillColor.alpha() ) );
2369 url.addQueryItem( QStringLiteral(
"fill" ), QStringLiteral(
"#000000" ) );
2370 url.addQueryItem( QStringLiteral(
"fill-opacity" ), QStringLiteral(
"1" ) );
2372 if ( strokeColor.isValid() )
2374 url.addQueryItem( QStringLiteral(
"outline" ), strokeColor.name() );
2375 url.addQueryItem( QStringLiteral(
"outline-opacity" ),
encodeSldAlpha( strokeColor.alpha() ) );
2379 url.addQueryItem( QStringLiteral(
"outline" ), QStringLiteral(
"#000000" ) );
2380 url.addQueryItem( QStringLiteral(
"outline-opacity" ), QStringLiteral(
"1" ) );
2382 url.addQueryItem( QStringLiteral(
"outline-width" ), QString::number( strokeWidth ) );
2383 const QString params = url.toString( QUrl::FullyEncoded );
2384 if ( params.isEmpty() )
2390 return basePath +
"?" + params;
2395 QString &path, QString &mime,
2396 QColor &color,
double &size )
2401 QDomElement externalGraphicElem = element.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
2402 if ( externalGraphicElem.isNull() )
2407 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2408 if ( !sizeElem.isNull() )
2411 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2420 const QString &path,
const QString &format,
int *markIndex,
2421 const QColor &color,
double size )
2423 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2424 element.appendChild( markElem );
2430 QDomElement markIndexElem = doc.createElement( QStringLiteral(
"se:MarkIndex" ) );
2431 markIndexElem.appendChild( doc.createTextNode( QString::number( *markIndex ) ) );
2432 markElem.appendChild( markIndexElem );
2436 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2437 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2438 markElem.appendChild( fillElem );
2443 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2445 element.appendChild( sizeElem );
2450 QString &path, QString &format,
int &markIndex,
2451 QColor &color,
double &size )
2459 QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2460 if ( markElem.isNull() )
2465 const QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
2466 if ( !markIndexElem.isNull() )
2469 const int i = markIndexElem.firstChild().nodeValue().toInt( &ok );
2475 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2476 Qt::BrushStyle b = Qt::SolidPattern;
2481 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2482 if ( !sizeElem.isNull() )
2485 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2494 const QString &name,
const QColor &color,
const QColor &strokeColor, Qt::PenStyle strokeStyle,
2495 double strokeWidth,
double size )
2497 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2498 element.appendChild( markElem );
2500 QDomElement wellKnownNameElem = doc.createElement( QStringLiteral(
"se:WellKnownName" ) );
2501 wellKnownNameElem.appendChild( doc.createTextNode( name ) );
2502 markElem.appendChild( wellKnownNameElem );
2505 if ( color.isValid() )
2507 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2508 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2509 markElem.appendChild( fillElem );
2513 if ( strokeColor.isValid() )
2515 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
2516 lineToSld( doc, strokeElem, strokeStyle, strokeColor, strokeWidth );
2517 markElem.appendChild( strokeElem );
2523 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2525 element.appendChild( sizeElem );
2530 QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle,
2531 double &strokeWidth,
double &size )
2535 name = QStringLiteral(
"square" );
2537 strokeColor = QColor( 0, 0, 0 );
2541 const QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2542 if ( markElem.isNull() )
2545 const QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
2546 if ( !wellKnownNameElem.isNull() )
2548 name = wellKnownNameElem.firstChild().nodeValue();
2549 QgsDebugMsg(
"found Mark with well known name: " + name );
2553 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2554 Qt::BrushStyle b = Qt::SolidPattern;
2559 QDomElement strokeElem = markElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2560 lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth );
2564 const QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2565 if ( !sizeElem.isNull() )
2568 const double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2578 if ( !rotationFunc.isEmpty() )
2580 QDomElement rotationElem = doc.createElement( QStringLiteral(
"se:Rotation" ) );
2582 element.appendChild( rotationElem );
2588 QDomElement rotationElem = element.firstChildElement( QStringLiteral(
"Rotation" ) );
2589 if ( !rotationElem.isNull() )
2599 if ( !alphaFunc.isEmpty() )
2601 QDomElement opacityElem = doc.createElement( QStringLiteral(
"se:Opacity" ) );
2603 element.appendChild( opacityElem );
2609 QDomElement opacityElem = element.firstChildElement( QStringLiteral(
"Opacity" ) );
2610 if ( !opacityElem.isNull() )
2619 if ( offset.isNull() )
2622 QDomElement displacementElem = doc.createElement( QStringLiteral(
"se:Displacement" ) );
2623 element.appendChild( displacementElem );
2625 QDomElement dispXElem = doc.createElement( QStringLiteral(
"se:DisplacementX" ) );
2626 dispXElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.x(), 2 ) ) );
2628 QDomElement dispYElem = doc.createElement( QStringLiteral(
"se:DisplacementY" ) );
2629 dispYElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.y(), 2 ) ) );
2631 displacementElem.appendChild( dispXElem );
2632 displacementElem.appendChild( dispYElem );
2639 QDomElement anchorElem = doc.createElement( QStringLiteral(
"se:AnchorPoint" ) );
2640 element.appendChild( anchorElem );
2642 QDomElement anchorXElem = doc.createElement( QStringLiteral(
"se:AnchorPointX" ) );
2643 anchorXElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.x() ) ) );
2645 QDomElement anchorYElem = doc.createElement( QStringLiteral(
"se:AnchorPointY" ) );
2646 anchorYElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.y() ) ) );
2648 anchorElem.appendChild( anchorXElem );
2649 anchorElem.appendChild( anchorYElem );
2654 offset = QPointF( 0, 0 );
2656 const QDomElement displacementElem = element.firstChildElement( QStringLiteral(
"Displacement" ) );
2657 if ( displacementElem.isNull() )
2660 const QDomElement dispXElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementX" ) );
2661 if ( !dispXElem.isNull() )
2664 const double offsetX = dispXElem.firstChild().nodeValue().toDouble( &ok );
2666 offset.setX( offsetX );
2669 const QDomElement dispYElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementY" ) );
2670 if ( !dispYElem.isNull() )
2673 const double offsetY = dispYElem.firstChild().nodeValue().toDouble( &ok );
2675 offset.setY( offsetY );
2682 const QString &label,
const QFont &font,
2683 const QColor &color,
double size )
2685 QDomElement labelElem = doc.createElement( QStringLiteral(
"se:Label" ) );
2686 labelElem.appendChild( doc.createTextNode( label ) );
2687 element.appendChild( labelElem );
2689 QDomElement fontElem = doc.createElement( QStringLiteral(
"se:Font" ) );
2690 element.appendChild( fontElem );
2694 fontElem.appendChild( createSldParameterElement( doc,
"font-style",
encodeSldFontStyle( font.style() ) ) );
2695 fontElem.appendChild( createSldParameterElement( doc,
"font-weight",
encodeSldFontWeight( font.weight() ) ) );
2700 if ( color.isValid() )
2702 QDomElement fillElem = doc.createElement( QStringLiteral(
"Fill" ) );
2703 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2704 element.appendChild( fillElem );
2709 Qt::PenJoinStyle joinStyle,
2710 Qt::PenCapStyle capStyle,
2712 const QVector<qreal> *dashPattern )
2715 penStyle.append(
"PEN(" );
2716 penStyle.append(
"c:" );
2717 penStyle.append(
c.name() );
2718 penStyle.append(
",w:" );
2720 penStyle.append( QString::number( width * mmScaleFactor ) );
2721 penStyle.append(
"mm" );
2724 if ( dashPattern && !dashPattern->isEmpty() )
2726 penStyle.append(
",p:\"" );
2727 QVector<qreal>::const_iterator pIt = dashPattern->constBegin();
2728 for ( ; pIt != dashPattern->constEnd(); ++pIt )
2730 if ( pIt != dashPattern->constBegin() )
2732 penStyle.append(
' ' );
2734 penStyle.append( QString::number( *pIt * mapUnitScaleFactor ) );
2735 penStyle.append(
'g' );
2737 penStyle.append(
'\"' );
2741 penStyle.append(
",cap:" );
2745 penStyle.append(
'p' );
2748 penStyle.append(
'r' );
2752 penStyle.append(
'b' );
2756 penStyle.append(
",j:" );
2757 switch ( joinStyle )
2760 penStyle.append(
'b' );
2763 penStyle.append(
'r' );
2767 penStyle.append(
'm' );
2773 penStyle.append(
",dp:" );
2774 penStyle.append( QString::number( offset * mapUnitScaleFactor ) );
2775 penStyle.append(
'g' );
2778 penStyle.append(
')' );
2785 brushStyle.append(
"BRUSH(" );
2786 brushStyle.append(
"fc:" );
2787 brushStyle.append( fillColor.name() );
2788 brushStyle.append(
')' );
2794 if ( geomFunc.isEmpty() )
2797 QDomElement geometryElem = doc.createElement( QStringLiteral(
"Geometry" ) );
2798 element.appendChild( geometryElem );
2828 QDomElement geometryElem = element.firstChildElement( QStringLiteral(
"Geometry" ) );
2829 if ( geometryElem.isNull() )
2841 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " +
function ) );
2845 if ( !filterElem.isNull() )
2846 element.appendChild( filterElem );
2857 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " +
function ) );
2861 if ( !filterElem.isNull() )
2862 element.appendChild( filterElem );
2869 QDomElement elem = element;
2870 if ( element.tagName() != QLatin1String(
"Filter" ) )
2872 const QDomNodeList filterNodes = element.elementsByTagName( QStringLiteral(
"Filter" ) );
2873 if ( !filterNodes.isEmpty() )
2875 elem = filterNodes.at( 0 ).toElement();
2879 if ( elem.isNull() )
2904 const QString &path,
const QString &format )
2908 QDomElement onlineResourceElem = doc.createElement( QStringLiteral(
"se:OnlineResource" ) );
2909 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
2910 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:href" ), url );
2911 element.appendChild( onlineResourceElem );
2913 QDomElement formatElem = doc.createElement( QStringLiteral(
"se:Format" ) );
2914 formatElem.appendChild( doc.createTextNode( format ) );
2915 element.appendChild( formatElem );
2922 const QDomElement onlineResourceElem = element.firstChildElement( QStringLiteral(
"OnlineResource" ) );
2923 if ( onlineResourceElem.isNull() )
2926 path = onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) );
2928 const QDomElement formatElem = element.firstChildElement( QStringLiteral(
"Format" ) );
2929 if ( formatElem.isNull() )
2932 format = formatElem.firstChild().nodeValue();
2939 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:SvgParameter" ) );
2940 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
2941 nodeElem.appendChild( doc.createTextNode( value ) );
2950 QDomElement paramElem = element.firstChildElement();
2951 while ( !paramElem.isNull() )
2953 if ( paramElem.localName() == QLatin1String(
"SvgParameter" ) || paramElem.localName() == QLatin1String(
"CssParameter" ) )
2955 const QString name = paramElem.attribute( QStringLiteral(
"name" ) );
2956 if ( paramElem.firstChild().nodeType() == QDomNode::TextNode )
2958 value = paramElem.firstChild().nodeValue();
2962 if ( paramElem.firstChild().nodeType() == QDomNode::ElementNode &&
2963 paramElem.firstChild().localName() == QLatin1String(
"Literal" ) )
2965 QgsDebugMsg( paramElem.firstChild().localName() );
2966 value = paramElem.firstChild().firstChild().nodeValue();
2970 QgsDebugMsg( QStringLiteral(
"unexpected child of %1" ).arg( paramElem.localName() ) );
2974 if ( !name.isEmpty() && !value.isEmpty() )
2975 params[ name ] = value;
2978 paramElem = paramElem.nextSiblingElement();
2986 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:VendorOption" ) );
2987 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
2988 nodeElem.appendChild( doc.createTextNode( value ) );
2996 QDomElement paramElem = element.firstChildElement( QStringLiteral(
"VendorOption" ) );
2997 while ( !paramElem.isNull() )
2999 const QString name = paramElem.attribute( QStringLiteral(
"name" ) );
3000 const QString value = paramElem.firstChild().nodeValue();
3002 if ( !name.isEmpty() && !value.isEmpty() )
3003 params[ name ] = value;
3005 paramElem = paramElem.nextSiblingElement( QStringLiteral(
"VendorOption" ) );
3015 if ( newSymbols.type() == QVariant::Map )
3017 return newSymbols.toMap();
3024 QDomElement e = element.firstChildElement();
3025 while ( !e.isNull() )
3027 if ( e.tagName() == QLatin1String(
"prop" ) )
3029 const QString propKey = e.attribute( QStringLiteral(
"k" ) );
3030 const QString propValue = e.attribute( QStringLiteral(
"v" ) );
3031 props[propKey] = propValue;
3033 e = e.nextSiblingElement();
3048 for ( QVariantMap::iterator it = props.begin(); it != props.end(); ++it )
3050 QDomElement propEl = doc.createElement( QStringLiteral(
"prop" ) );
3051 propEl.setAttribute( QStringLiteral(
"k" ), it.key() );
3052 propEl.setAttribute( QStringLiteral(
"v" ), it.value().toString() );
3053 element.appendChild( propEl );
3063 QDomElement e = element.firstChildElement();
3065 while ( !e.isNull() )
3067 if ( e.tagName() == QLatin1String(
"symbol" ) )
3071 symbols.insert( e.attribute( QStringLiteral(
"name" ) ), symbol );
3077 e = e.nextSiblingElement();
3084 QStringList subsymbols;
3086 for ( QMap<QString, QgsSymbol *>::iterator it = symbols.begin(); it != symbols.end(); ++it )
3088 if ( it.key()[0] !=
'@' )
3092 subsymbols.append( it.key() );
3094 QStringList parts = it.key().split(
'@' );
3095 if ( parts.count() < 3 )
3097 QgsDebugMsg(
"found subsymbol with invalid name: " + it.key() );
3101 const QString symname = parts[1];
3102 const int symlayer = parts[2].toInt();
3104 if ( !symbols.contains( symname ) )
3106 QgsDebugMsg(
"subsymbol references invalid symbol: " + symname );
3114 QgsDebugMsg(
"subsymbol references invalid symbol layer: " + QString::number( symlayer ) );
3123 QgsDebugMsg(
"symbol layer refused subsymbol: " + it.key() );
3130 for (
int i = 0; i < subsymbols.count(); i++ )
3131 symbols.take( subsymbols[i] );
3138 QDomElement symbolsElem = doc.createElement( tagName );
3141 for ( QMap<QString, QgsSymbol *>::iterator its = symbols.begin(); its != symbols.end(); ++its )
3143 const QDomElement symEl =
saveSymbol( its.key(), its.value(), doc, context );
3144 symbolsElem.appendChild( symEl );
3152 qDeleteAll( symbols );
3161 std::unique_ptr< QMimeData >mimeData(
new QMimeData );
3163 QDomDocument symbolDoc;
3165 symbolDoc.appendChild( symbolElem );
3166 mimeData->setText( symbolDoc.toString() );
3169 mimeData->setColorData( symbol->
color() );
3171 return mimeData.release();
3179 const QString text = data->text();
3180 if ( !text.isEmpty() )
3185 if ( doc.setContent( text ) )
3187 elem = doc.documentElement();
3189 if ( elem.nodeName() != QLatin1String(
"symbol" ) )
3190 elem = elem.firstChildElement( QStringLiteral(
"symbol" ) );
3201 const QString rampType = element.attribute( QStringLiteral(
"type" ) );
3218 QgsDebugMsg(
"unknown colorramp type " + rampType );
3226 QDomElement rampEl = doc.createElement( QStringLiteral(
"colorramp" ) );
3227 rampEl.setAttribute( QStringLiteral(
"type" ), ramp->
type() );
3228 rampEl.setAttribute( QStringLiteral(
"name" ), name );
3236 QVariantMap rampMap;
3238 rampMap.insert( QStringLiteral(
"type" ), ramp->
type() );
3239 rampMap.insert( QStringLiteral(
"name" ), name );
3241 const QVariantMap properties = ramp->
properties();
3243 QVariantMap propertyMap;
3244 for (
auto property = properties.constBegin(); property != properties.constEnd(); ++property )
3246 propertyMap.insert( property.key(), property.value() );
3249 rampMap.insert( QStringLiteral(
"properties" ), propertyMap );
3255 const QVariantMap rampMap = value.toMap();
3257 const QString rampType = rampMap.
value( QStringLiteral(
"type" ) ).toString();
3260 const QVariantMap propertyMap = rampMap.value( QStringLiteral(
"properties" ) ).toMap();
3263 for (
auto property = propertyMap.constBegin(); property != propertyMap.constEnd(); ++property )
3265 props.insert( property.key(), property.value().toString() );
3280 QgsDebugMsg(
"unknown colorramp type " + rampType );
3287 if ( !color.isValid() )
3294 return color.name();
3299 QList<QColor> colors;
3302 const thread_local QRegularExpression sepCommaSpaceRegExp(
"(,|\\s)" );
3303 QStringList components = colorStr.simplified().split( sepCommaSpaceRegExp );
3304 QStringList::iterator it = components.begin();
3305 for ( ; it != components.end(); ++it )
3307 const QColor result =
parseColor( *it,
true );
3308 if ( result.isValid() )
3313 if ( colors.length() > 0 )
3319 const thread_local QRegularExpression sepCommaRegExp(
"(,|\n)" );
3320 components = colorStr.split( sepCommaRegExp );
3321 it = components.begin();
3322 for ( ; it != components.end(); ++it )
3324 const QColor result =
parseColor( *it,
true );
3325 if ( result.isValid() )
3330 if ( colors.length() > 0 )
3336 components = colorStr.simplified().split( QString(
' ' ) );
3337 it = components.begin();
3338 for ( ; it != components.end(); ++it )
3340 const QColor result =
parseColor( *it,
true );
3341 if ( result.isValid() )
3346 if ( colors.length() > 0 )
3352 components = colorStr.split(
'\n' );
3353 it = components.begin();
3354 for ( ; it != components.end(); ++it )
3356 const QColor result =
parseColor( *it,
true );
3357 if ( result.isValid() )
3370 QMimeData *mimeData =
new QMimeData;
3371 mimeData->setColorData( QVariant( color ) );
3372 mimeData->setText( color.name() );
3379 if ( mimeData->hasColor() )
3381 QColor mimeColor = mimeData->colorData().value<QColor>();
3382 if ( mimeColor.isValid() )
3390 if ( mimeData->hasText() )
3394 if ( textColor.isValid() )
3409 if ( data->hasFormat( QStringLiteral(
"text/xml" ) ) )
3412 const QByteArray encodedData = data->data( QStringLiteral(
"text/xml" ) );
3413 QDomDocument xmlDoc;
3414 xmlDoc.setContent( encodedData );
3416 const QDomElement dragDataElem = xmlDoc.documentElement();
3417 if ( dragDataElem.tagName() == QLatin1String(
"ColorSchemeModelDragData" ) )
3419 const QDomNodeList nodeList = dragDataElem.childNodes();
3420 const int nChildNodes = nodeList.size();
3421 QDomElement currentElem;
3423 for (
int i = 0; i < nChildNodes; ++i )
3425 currentElem = nodeList.at( i ).toElement();
3426 if ( currentElem.isNull() )
3431 QPair< QColor, QString> namedColor;
3433 namedColor.second = currentElem.attribute( QStringLiteral(
"label" ), QString() );
3435 mimeColors << namedColor;
3440 if ( mimeColors.length() == 0 && data->hasFormat( QStringLiteral(
"application/x-colorobject-list" ) ) )
3443 const QByteArray encodedData = data->data( QStringLiteral(
"application/x-colorobject-list" ) );
3444 QDomDocument xmlDoc;
3445 xmlDoc.setContent( encodedData );
3447 const QDomNodeList colorsNodes = xmlDoc.elementsByTagName( QStringLiteral(
"colors" ) );
3448 if ( colorsNodes.length() > 0 )
3450 const QDomElement colorsElem = colorsNodes.at( 0 ).toElement();
3451 const QDomNodeList colorNodeList = colorsElem.childNodes();
3452 const int nChildNodes = colorNodeList.size();
3453 QDomElement currentElem;
3455 for (
int i = 0; i < nChildNodes; ++i )
3458 currentElem = colorNodeList.at( i ).toElement();
3459 if ( currentElem.isNull() )
3464 const QDomNodeList colorNodes = currentElem.elementsByTagName( QStringLiteral(
"color" ) );
3465 const QDomNodeList nameNodes = currentElem.elementsByTagName( QStringLiteral(
"name" ) );
3467 if ( colorNodes.length() > 0 )
3469 const QDomElement colorElem = colorNodes.at( 0 ).toElement();
3471 const QStringList colorParts = colorElem.text().simplified().split(
' ' );
3472 if ( colorParts.length() < 3 )
3477 const int red = colorParts.at( 0 ).toDouble() * 255;
3478 const int green = colorParts.at( 1 ).toDouble() * 255;
3479 const int blue = colorParts.at( 2 ).toDouble() * 255;
3480 QPair< QColor, QString> namedColor;
3481 namedColor.first = QColor( red, green, blue );
3482 if ( nameNodes.length() > 0 )
3484 const QDomElement nameElem = nameNodes.at( 0 ).toElement();
3485 namedColor.second = nameElem.text();
3487 mimeColors << namedColor;
3493 if ( mimeColors.length() == 0 && data->hasText() )
3497 QList< QColor >::iterator it = parsedColors.begin();
3498 for ( ; it != parsedColors.end(); ++it )
3500 mimeColors << qMakePair( *it, QString() );
3504 if ( mimeColors.length() == 0 && data->hasColor() )
3507 const QColor mimeColor = data->colorData().value<QColor>();
3508 if ( mimeColor.isValid() )
3510 mimeColors << qMakePair( mimeColor, QString() );
3520 QMimeData *mimeData =
new QMimeData();
3521 QDomDocument xmlDoc;
3522 QDomElement xmlRootElement = xmlDoc.createElement( QStringLiteral(
"ColorSchemeModelDragData" ) );
3523 xmlDoc.appendChild( xmlRootElement );
3525 QgsNamedColorList::const_iterator colorIt = colorList.constBegin();
3526 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3528 QDomElement namedColor = xmlDoc.createElement( QStringLiteral(
"NamedColor" ) );
3530 namedColor.setAttribute( QStringLiteral(
"label" ), ( *colorIt ).second );
3531 xmlRootElement.appendChild( namedColor );
3533 mimeData->setData( QStringLiteral(
"text/xml" ), xmlDoc.toByteArray() );
3541 colorIt = colorList.constBegin();
3542 QStringList colorListString;
3543 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3545 colorListString << ( *colorIt ).first.name();
3547 mimeData->setText( colorListString.join( QLatin1Char(
'\n' ) ) );
3550 if ( colorList.length() > 0 )
3552 mimeData->setColorData( QVariant( colorList.at( 0 ).first ) );
3560 if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3565 QTextStream stream( &file );
3566 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3567 stream <<
"GIMP Palette" << endl;
3569 stream <<
"GIMP Palette" << Qt::endl;
3571 if ( paletteName.isEmpty() )
3573 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3574 stream <<
"Name: QGIS Palette" << endl;
3576 stream <<
"Name: QGIS Palette" << Qt::endl;
3581 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3582 stream <<
"Name: " << paletteName << endl;
3584 stream <<
"Name: " << paletteName << Qt::endl;
3587 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3588 stream <<
"Columns: 4" << endl;
3589 stream <<
'#' << endl;
3591 stream <<
"Columns: 4" << Qt::endl;
3592 stream <<
'#' << Qt::endl;
3595 for ( QgsNamedColorList::ConstIterator colorIt = colors.constBegin(); colorIt != colors.constEnd(); ++colorIt )
3597 const QColor color = ( *colorIt ).first;
3598 if ( !color.isValid() )
3602 stream << QStringLiteral(
"%1 %2 %3" ).arg( color.red(), 3 ).arg( color.green(), 3 ).arg( color.blue(), 3 );
3603 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3604 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << endl;
3606 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << Qt::endl;
3618 if ( !file.open( QIODevice::ReadOnly ) )
3621 return importedColors;
3624 QTextStream in( &file );
3626 QString line = in.readLine();
3627 if ( !line.startsWith( QLatin1String(
"GIMP Palette" ) ) )
3630 return importedColors;
3634 while ( !in.atEnd() && !line.startsWith( QLatin1String(
"Name:" ) ) && !line.startsWith(
'#' ) )
3636 line = in.readLine();
3638 if ( line.startsWith( QLatin1String(
"Name:" ) ) )
3640 const thread_local QRegularExpression nameRx(
"Name:\\s*(\\S.*)$" );
3641 const QRegularExpressionMatch match = nameRx.match( line );
3642 if ( match.hasMatch() )
3644 name = match.captured( 1 );
3649 while ( !in.atEnd() && !line.startsWith(
'#' ) )
3651 line = in.readLine();
3656 return importedColors;
3660 const thread_local QRegularExpression rx(
"^\\s*(\\d+)\\s+(\\d+)\\s+(\\d+)(\\s.*)?$" );
3661 while ( !in.atEnd() )
3663 line = in.readLine();
3664 const QRegularExpressionMatch match = rx.match( line );
3665 if ( !match.hasMatch() )
3669 const int red = match.captured( 1 ).toInt();
3670 const int green = match.captured( 2 ).toInt();
3671 const int blue = match.captured( 3 ).toInt();
3672 const QColor color = QColor( red, green, blue );
3673 if ( !color.isValid() )
3680 if ( rx.captureCount() > 3 )
3682 label = match.captured( 4 ).simplified();
3689 importedColors << qMakePair( color, label );
3694 return importedColors;
3707 const thread_local QRegularExpression hexColorAlphaRx(
"^\\s*#?([0-9a-fA-F]{6})([0-9a-fA-F]{2})\\s*$" );
3708 QRegularExpressionMatch match = hexColorAlphaRx.match( colorStr );
3711 if ( !match.hasMatch() && QColor::isValidColor( colorStr ) )
3714 parsedColor.setNamedColor( colorStr );
3715 if ( parsedColor.isValid() )
3717 containsAlpha =
false;
3723 if ( match.hasMatch() )
3725 const QString hexColor = match.captured( 1 );
3726 parsedColor.setNamedColor( QStringLiteral(
"#" ) + hexColor );
3728 const int alphaHex = match.captured( 2 ).toInt( &alphaOk, 16 );
3730 if ( parsedColor.isValid() && alphaOk )
3732 parsedColor.setAlpha( alphaHex );
3733 containsAlpha =
true;
3741 const thread_local QRegularExpression hexColorRx2(
"^\\s*(?:[0-9a-fA-F]{3}){1,2}\\s*$" );
3742 if ( colorStr.indexOf( hexColorRx2 ) != -1 )
3745 parsedColor.setNamedColor( QStringLiteral(
"#" ) + colorStr );
3746 if ( parsedColor.isValid() )
3748 containsAlpha =
false;
3755 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*$" );
3756 match = rgbFormatRx.match( colorStr );
3757 if ( match.hasMatch() )
3759 const int r = match.captured( 1 ).toInt();
3760 const int g = match.captured( 2 ).toInt();
3761 const int b = match.captured( 3 ).toInt();
3762 parsedColor.setRgb( r, g, b );
3763 if ( parsedColor.isValid() )
3765 containsAlpha =
false;
3771 const thread_local QRegularExpression hslFormatRx(
"^\\s*hsl\\(?\\s*(\\d+)\\s*,\\s*(\\d+)\\s*%\\s*,\\s*(\\d+)\\s*%\\s*\\)?\\s*;?\\s*$" );
3772 match = hslFormatRx.match( colorStr );
3773 if ( match.hasMatch() )
3775 const int h = match.captured( 1 ).toInt();
3776 const int s = match.captured( 2 ).toInt();
3777 const int l = match.captured( 3 ).toInt();
3778 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0 );
3779 if ( parsedColor.isValid() )
3781 containsAlpha =
false;
3787 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*$" );
3788 match = rgbPercentFormatRx.match( colorStr );
3789 if ( match.hasMatch() )
3791 const int r = std::round( match.captured( 1 ).toDouble() * 2.55 );
3792 const int g = std::round( match.captured( 2 ).toDouble() * 2.55 );
3793 const int b = std::round( match.captured( 3 ).toDouble() * 2.55 );
3794 parsedColor.setRgb( r, g, b );
3795 if ( parsedColor.isValid() )
3797 containsAlpha =
false;
3803 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*$" );
3804 match = rgbaFormatRx.match( colorStr );
3805 if ( match.hasMatch() )
3807 const int r = match.captured( 1 ).toInt();
3808 const int g = match.captured( 2 ).toInt();
3809 const int b = match.captured( 3 ).toInt();
3810 const int a = std::round( match.captured( 4 ).toDouble() * 255.0 );
3811 parsedColor.setRgb( r, g, b, a );
3812 if ( parsedColor.isValid() )
3814 containsAlpha =
true;
3820 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*$" );
3821 match = rgbaPercentFormatRx.match( colorStr );
3822 if ( match.hasMatch() )
3824 const int r = std::round( match.captured( 1 ).toDouble() * 2.55 );
3825 const int g = std::round( match.captured( 2 ).toDouble() * 2.55 );
3826 const int b = std::round( match.captured( 3 ).toDouble() * 2.55 );
3827 const int a = std::round( match.captured( 4 ).toDouble() * 255.0 );
3828 parsedColor.setRgb( r, g, b, a );
3829 if ( parsedColor.isValid() )
3831 containsAlpha =
true;
3837 const thread_local QRegularExpression hslaPercentFormatRx(
"^\\s*hsla\\(?\\s*(\\d+)\\s*,\\s*(\\d+)\\s*%\\s*,\\s*(\\d+)\\s*%\\s*,\\s*([\\d\\.]+)\\s*\\)?\\s*;?\\s*$" );
3838 match = hslaPercentFormatRx.match( colorStr );
3839 if ( match.hasMatch() )
3841 const int h = match.captured( 1 ).toInt();
3842 const int s = match.captured( 2 ).toInt();
3843 const int l = match.captured( 3 ).toInt();
3844 const int a = std::round( match.captured( 4 ).toDouble() * 255.0 );
3845 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0, a );
3846 if ( parsedColor.isValid() )
3848 containsAlpha =
true;
3865 const QImage::Format format = image->format();
3866 if ( format != QImage::Format_ARGB32_Premultiplied && format != QImage::Format_ARGB32 )
3868 QgsDebugMsg( QStringLiteral(
"no alpha channel." ) );
3873 for (
int heightIndex = 0; heightIndex < image->height(); ++heightIndex )
3875 QRgb *scanLine =
reinterpret_cast< QRgb *
>( image->scanLine( heightIndex ) );
3876 for (
int widthIndex = 0; widthIndex < image->width(); ++widthIndex )
3878 myRgb = scanLine[widthIndex];
3879 if ( format == QImage::Format_ARGB32_Premultiplied )
3880 scanLine[widthIndex] = qRgba( opacity * qRed( myRgb ), opacity * qGreen( myRgb ), opacity * qBlue( myRgb ), opacity * qAlpha( myRgb ) );
3882 scanLine[widthIndex] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), opacity * qAlpha( myRgb ) );
3890 const int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
3891 const int alpha = ( radius < 1 ) ? 16 : ( radius > 17 ) ? 1 : tab[radius - 1];
3893 if ( image.format() != QImage::Format_ARGB32_Premultiplied
3894 && image.format() != QImage::Format_RGB32 )
3896 image = image.convertToFormat( QImage::Format_ARGB32_Premultiplied );
3899 const int r1 = rect.top();
3900 const int r2 = rect.bottom();
3901 const int c1 = rect.left();
3902 const int c2 = rect.right();
3904 const int bpl = image.bytesPerLine();
3912 i1 = i2 = ( QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3 );
3914 for (
int col = c1; col <= c2; col++ )
3916 p = image.scanLine( r1 ) + col * 4;
3917 for (
int i = i1; i <= i2; i++ )
3918 rgba[i] = p[i] << 4;
3921 for (
int j = r1; j < r2; j++, p += bpl )
3922 for (
int i = i1; i <= i2; i++ )
3923 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
3926 for (
int row = r1; row <= r2; row++ )
3928 p = image.scanLine( row ) + c1 * 4;
3929 for (
int i = i1; i <= i2; i++ )
3930 rgba[i] = p[i] << 4;
3933 for (
int j = c1; j < c2; j++, p += 4 )
3934 for (
int i = i1; i <= i2; i++ )
3935 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
3938 for (
int col = c1; col <= c2; col++ )
3940 p = image.scanLine( r2 ) + col * 4;
3941 for (
int i = i1; i <= i2; i++ )
3942 rgba[i] = p[i] << 4;
3945 for (
int j = r1; j < r2; j++, p -= bpl )
3946 for (
int i = i1; i <= i2; i++ )
3947 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
3950 for (
int row = r1; row <= r2; row++ )
3952 p = image.scanLine( row ) + c2 * 4;
3953 for (
int i = i1; i <= i2; i++ )
3954 rgba[i] = p[i] << 4;
3957 for (
int j = c1; j < c2; j++, p -= 4 )
3958 for (
int i = i1; i <= i2; i++ )
3959 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
3965 if ( alpha != 255 && alpha > 0 )
3969 const double alphaFactor = alpha / 255.;
3970 int r = 0, g = 0, b = 0;
3971 rgb.getRgb( &r, &g, &b );
3976 rgb.setRgb( r, g, b, alpha );
3978 else if ( alpha == 0 )
3980 rgb.setRgb( 0, 0, 0, 0 );
3989 if ( !simpleFill || !simpleLine )
4013 if ( simpleLine->
offset() )
4031 if ( order == Qt::AscendingOrder )
4045 const double dx = directionPoint.x() - startPoint.x();
4046 const double dy = directionPoint.y() - startPoint.y();
4047 const double length = std::sqrt( dx * dx + dy * dy );
4048 const double scaleFactor = distance / length;
4049 return QPointF( startPoint.x() + dx * scaleFactor, startPoint.y() + dy * scaleFactor );
4059 for (
int i = 0; i < svgPaths.size(); i++ )
4061 const QDir dir( svgPaths[i] );
4062 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4063 for (
const QString &item : svgSubPaths )
4065 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4068 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4069 for (
const QString &item : svgFiles )
4072 list.append( dir.path() +
'/' + item );
4084 QStringList svgPaths;
4085 svgPaths.append( directory );
4087 for (
int i = 0; i < svgPaths.size(); i++ )
4089 const QDir dir( svgPaths[i] );
4090 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4091 for (
const QString &item : svgSubPaths )
4093 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4096 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4097 for (
const QString &item : svgFiles )
4099 list.append( dir.path() +
'/' + item );
4111 if ( n.startsWith( QLatin1String(
"base64:" ) ) )
4115 if ( QFileInfo::exists( n ) )
4116 return QFileInfo( n ).canonicalFilePath();
4120 if ( name.contains( QLatin1String(
"://" ) ) )
4122 const QUrl url( name );
4123 if ( url.isValid() && !url.scheme().isEmpty() )
4125 if ( url.scheme().compare( QLatin1String(
"file" ), Qt::CaseInsensitive ) == 0 )
4128 name = url.toLocalFile();
4129 if ( QFile( name ).exists() )
4131 return QFileInfo( name ).canonicalFilePath();
4145 for (
int i = 0; i < svgPaths.size(); i++ )
4147 QString svgPath = svgPaths[i];
4148 if ( svgPath.endsWith( QChar(
'/' ) ) )
4159 const QString myLocalPath = svgPath + QDir::separator() + name;
4162 if ( QFile( myLocalPath ).exists() )
4165 return QFileInfo( myLocalPath ).canonicalFilePath();
4169 return pathResolver.
readPath( name );
4177 if ( p.startsWith( QLatin1String(
"base64:" ) ) )
4180 if ( !QFileInfo::exists( p ) )
4183 QString path = QFileInfo( p ).canonicalFilePath();
4187 bool isInSvgPaths =
false;
4188 for (
int i = 0; i < svgPaths.size(); i++ )
4190 const QString dir = QFileInfo( svgPaths[i] ).canonicalFilePath();
4192 if ( !dir.isEmpty() && path.startsWith( dir ) )
4194 path = path.mid( dir.size() + 1 );
4195 isInSvgPaths =
true;
4210 double cx = 0, cy = 0;
4211 double area, sum = 0;
4212 for (
int i = points.count() - 1, j = 0; j < points.count(); i = j++ )
4214 const QPointF &p1 = points[i];
4215 const QPointF &p2 = points[j];
4216 area = p1.x() * p2.y() - p1.y() * p2.x();
4218 cx += ( p1.x() + p2.x() ) * area;
4219 cy += ( p1.y() + p2.y() ) * area;
4226 if ( points.count() >= 2 )
4227 return QPointF( ( points[0].x() + points[1].x() ) / 2, ( points[0].y() + points[1].y() ) / 2 );
4228 else if ( points.count() == 1 )
4236 return QPointF( cx, cy );
4245 unsigned int i, pointCount = points.count();
4247 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( points[i].x(), points[i].y() );
4253 for (
auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
4255 pointCount = ( *ringIt ).count();
4257 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( ( *ringIt )[i].x(), ( *ringIt )[i].y() );
4263 if ( !pointOnSurfaceGeom.
isNull() )
4277 bool inside =
false;
4279 const double x = point.x();
4280 const double y = point.y();
4282 for (
int i = 0, j = points.count() - 1; i < points.count(); i++ )
4284 const QPointF &p1 = points[i];
4285 const QPointF &p2 = points[j];
4290 if ( ( p1.y() < y && p2.y() >= y ) || ( p2.y() < y && p1.y() >= y ) )
4292 if ( p1.x() + ( y - p1.y() ) / ( p2.y() - p1.y() ) * ( p2.x() - p1.x() ) <= x )
4303 if ( polyline.size() < 2 )
4306 double totalLength = 0;
4307 auto it = polyline.begin();
4309 for ( ; it != polyline.end(); ++it )
4311 const QPointF p2 = *it;
4312 const double segmentLength = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4313 totalLength += segmentLength;
4321 if ( polyline.size() < 2 )
4324 double totalLength = 0;
4325 auto it = polyline.begin();
4327 std::vector< double > segmentLengths( polyline.size() - 1 );
4328 auto segmentLengthIt = segmentLengths.begin();
4329 for ( ; it != polyline.end(); ++it )
4331 const QPointF p2 = *it;
4332 *segmentLengthIt = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4333 totalLength += *segmentLengthIt;
4339 if ( startOffset >= 0 && totalLength <= startOffset )
4341 if ( endOffset < 0 && totalLength <= -endOffset )
4344 const double startDistance = startOffset < 0 ? totalLength + startOffset : startOffset;
4345 const double endDistance = endOffset <= 0 ? totalLength + endOffset : endOffset;
4346 QPolygonF substringPoints;
4347 substringPoints.reserve( polyline.size() );
4349 it = polyline.begin();
4350 segmentLengthIt = segmentLengths.begin();
4353 bool foundStart =
false;
4354 if (
qgsDoubleNear( startDistance, 0.0 ) || startDistance < 0 )
4356 substringPoints << p1;
4360 double distanceTraversed = 0;
4361 for ( ; it != polyline.end(); ++it )
4363 const QPointF p2 = *it;
4364 if ( distanceTraversed < startDistance && distanceTraversed + *segmentLengthIt > startDistance )
4367 const double distanceToStart = startDistance - distanceTraversed;
4368 double startX, startY;
4370 substringPoints << QPointF( startX, startY );
4373 if ( foundStart && ( distanceTraversed + *segmentLengthIt > endDistance ) )
4376 const double distanceToEnd = endDistance - distanceTraversed;
4379 if ( substringPoints.last() != QPointF( endX, endY ) )
4380 substringPoints << QPointF( endX, endY );
4382 else if ( foundStart )
4384 if ( substringPoints.last() != QPointF( p2.x(), p2.y() ) )
4385 substringPoints << QPointF( p2.x(), p2.y() );
4388 distanceTraversed += *segmentLengthIt;
4389 if ( distanceTraversed > endDistance )
4396 if ( ( substringPoints.size() < 2 ) || ( substringPoints.size() == 2 && substringPoints.at( 0 ) == substringPoints.at( 1 ) ) )
4399 return substringPoints;
4404 double vertexAngle = M_PI - ( std::atan2( p3.y() - p2.y(), p3.x() - p2.x() ) - std::atan2( p2.y() - p1.y(), p2.x() - p1.x() ) );
4408 return vertexAngle < M_PI * 135.0 / 180.0 || vertexAngle > M_PI * 225.0 / 180.0;
4413 target.reserve( target.size() + line.size() );
4414 for (
const QPointF &pt : line )
4416 if ( !target.empty() && target.last() == pt )
4425 if ( fieldOrExpression.isEmpty() )
4460 QList<double> breaks;
4463 breaks.append( maximum );
4467 const int minimumCount =
static_cast< int >( classes ) / 3;
4468 const double shrink = 0.75;
4469 const double highBias = 1.5;
4470 const double adjustBias = 0.5 + 1.5 * highBias;
4471 const int divisions = classes;
4472 const double h = highBias;
4475 const double dx = maximum - minimum;
4485 cell = std::max( std::fabs( minimum ), std::fabs( maximum ) );
4486 if ( adjustBias >= 1.5 * h + 0.5 )
4488 U = 1 + ( 1.0 / ( 1 + h ) );
4492 U = 1 + ( 1.5 / ( 1 + adjustBias ) );
4494 small = dx < ( cell * U * std::max( 1, divisions ) * 1e-07 * 3.0 );
4501 cell = 9 + cell / 10;
4502 cell = cell * shrink;
4504 if ( minimumCount > 1 )
4506 cell = cell / minimumCount;
4512 if ( divisions > 1 )
4514 cell = cell / divisions;
4517 if ( cell < 20 * 1e-07 )
4522 const double base = std::pow( 10.0, std::floor( std::log10( cell ) ) );
4524 if ( ( 2 * base ) - cell < h * ( cell - unit ) )
4527 if ( ( 5 * base ) - cell < adjustBias * ( cell - unit ) )
4530 if ( ( 10.0 * base ) - cell < h * ( cell - unit ) )
4537 int start = std::floor( minimum / unit + 1e-07 );
4538 int end = std::ceil( maximum / unit - 1e-07 );
4541 while ( start * unit > minimum + ( 1e-07 * unit ) )
4545 while ( end * unit < maximum - ( 1e-07 * unit ) )
4549 QgsDebugMsg( QStringLiteral(
"pretty classes: %1" ).arg( end ) );
4553 int k = std::floor( 0.5 + end - start );
4554 if ( k < minimumCount )
4556 k = minimumCount - k;
4560 start = start - k / 2 + k % 2;
4564 start = start - k / 2;
4565 end = end + k / 2 + k % 2;
4568 const double minimumBreak = start * unit;
4570 const int count = end - start;
4572 breaks.reserve( count );
4573 for (
int i = 1; i < count + 1; i++ )
4575 breaks.append( minimumBreak + i * unit );
4578 if ( breaks.isEmpty() )
4581 if ( breaks.first() < minimum )
4583 breaks[0] = minimum;
4585 if ( breaks.last() > maximum )
4587 breaks[breaks.count() - 1] = maximum;
4592 if ( minimum < 0.0 && maximum > 0.0 )
4594 QList<double> breaksMinusZero;
4595 for (
int i = 0; i < breaks.count(); i++ )
4597 breaksMinusZero.append( breaks[i] - 0.0 );
4600 for (
int i = 1; i < breaks.count(); i++ )
4602 if ( std::abs( breaksMinusZero[i] ) < std::abs( breaksMinusZero[i - 1] ) )
4605 breaks[posOfMin] = 0.0;
4614 bool roundToUnit =
false;
4617 if ( props.contains( QStringLiteral(
"uomScale" ) ) )
4620 scale = props.value( QStringLiteral(
"uomScale" ) ).toDouble( &ok );
4629 if ( props.value( QStringLiteral(
"uom" ) ) == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
4654 scale = 1 / 0.28 * 25.4;
4678 double rescaled = size * scale;
4683 rescaled = std::round( rescaled );
4690 const double x =
rescaleUom( point.x(), unit, props );
4691 const double y =
rescaleUom( point.y(), unit, props );
4692 return QPointF( x, y );
4697 QVector<qreal> result;
4698 QVector<qreal>::const_iterator it = array.constBegin();
4699 for ( ; it != array.constEnd(); ++it )
4701 result.append(
rescaleUom( *it, unit, props ) );
4708 if ( !props.value( QStringLiteral(
"scaleMinDenom" ), QString() ).toString().isEmpty() )
4710 QDomElement scaleMinDenomElem = doc.createElement( QStringLiteral(
"se:MinScaleDenominator" ) );
4711 scaleMinDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMinDenom" ) ).toString().toDouble() ) ) );
4712 ruleElem.appendChild( scaleMinDenomElem );
4715 if ( !props.value( QStringLiteral(
"scaleMaxDenom" ), QString() ).toString().isEmpty() )
4717 QDomElement scaleMaxDenomElem = doc.createElement( QStringLiteral(
"se:MaxScaleDenominator" ) );
4718 scaleMaxDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMaxDenom" ) ).toString().toDouble() ) ) );
4719 ruleElem.appendChild( scaleMaxDenomElem );
4728 const double parentScaleMinDenom = props.value( QStringLiteral(
"scaleMinDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
4729 if ( !ok || parentScaleMinDenom <= 0 )
4730 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( mScaleMinDenom );
4732 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( std::max( parentScaleMinDenom, mScaleMinDenom ) );
4738 const double parentScaleMaxDenom = props.value( QStringLiteral(
"scaleMaxDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
4739 if ( !ok || parentScaleMaxDenom <= 0 )
4740 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( mScaleMaxDenom );
4742 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( std::min( parentScaleMaxDenom, mScaleMaxDenom ) );
4750 if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
4752 scale = 1.0 / 0.00028;
4754 else if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
4756 scale = 304.8 / 0.28;
4763 return size * scale;
4771 SymbolLayerVisitor(
const QSet<QgsSymbolLayerId> &layerIds )
4772 : mSymbolLayerIds( layerIds )
4785 void visitSymbol(
const QgsSymbol *symbol,
const QString &identifier, QVector<int> rootPath )
4789 QVector<int> indexPath = rootPath;
4790 indexPath.append( idx );
4792 if ( mSymbolLayerIds.contains(
QgsSymbolLayerId( mCurrentRuleKey + identifier, indexPath ) ) )
4794 mSymbolLayers.insert( sl );
4799 visitSymbol( subSymbol, identifier, indexPath );
4808 if ( symbolEntity->symbol() )
4810 visitSymbol( symbolEntity->symbol(), leaf.
identifier, {} );
4816 QString mCurrentRuleKey;
4817 const QSet<QgsSymbolLayerId> &mSymbolLayerIds;
4818 QSet<const QgsSymbolLayer *> mSymbolLayers;
4821 SymbolLayerVisitor visitor( symbolLayerIds );
4822 renderer->
accept( &visitor );
4823 return visitor.mSymbolLayers;
4828 if ( !s || !context )
4838 size = markerSymbol->
size( *context );
4840 else if ( lineSymbol )
4842 size = lineSymbol->
width( *context );
4851 if ( minSize > 0 && size < minSize )
4855 else if ( maxSize > 0 && size > maxSize )
4873 else if ( lineSymbol )
4887 QMap<QString, QgsProperty>::const_iterator paramIt = propertiesMap.constBegin();
4888 for ( ; paramIt != propertiesMap.constEnd(); ++paramIt )
4890 properties.insert( paramIt.key(), paramIt.value().valueAsString( context ) );
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,...
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...
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.
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
Set stroke color.
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 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 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 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 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 QgsSymbolLayer * createFillLayerFromSld(QDomElement &element)
static QDomElement createSvgParameterElement(QDomDocument &doc, const QString &name, const QString &value)
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...
virtual QColor color() const
The fill color.
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.
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.