48 #include <QDomDocument>
50 #include <QDomElement>
59 #include <QRegularExpression>
61 #define POINTS_TO_MM 2.83464567
65 return QStringLiteral(
"%1,%2,%3,%4" ).arg( color.red() ).arg( color.green() ).arg( color.blue() ).arg( color.alpha() );
70 const QStringList lst =
str.split(
',' );
71 if ( lst.count() < 3 )
75 int red, green, blue, alpha;
77 green = lst[1].toInt();
78 blue = lst[2].toInt();
80 if ( lst.count() > 3 )
82 alpha = lst[3].toInt();
84 return QColor( red, green, blue, alpha );
89 return QString::number( alpha / 255.0,
'g', 2 );
95 double alpha =
str.toDouble( &ok );
96 if ( !ok || alpha > 1 )
107 case QFont::StyleNormal:
108 return QStringLiteral(
"normal" );
109 case QFont::StyleItalic:
110 return QStringLiteral(
"italic" );
111 case QFont::StyleOblique:
112 return QStringLiteral(
"oblique" );
120 if (
str == QLatin1String(
"normal" ) )
return QFont::StyleNormal;
121 if (
str == QLatin1String(
"italic" ) )
return QFont::StyleItalic;
122 if (
str == QLatin1String(
"oblique" ) )
return QFont::StyleOblique;
123 return QFont::StyleNormal;
128 if ( weight == 50 )
return QStringLiteral(
"normal" );
129 if ( weight == 75 )
return QStringLiteral(
"bold" );
133 if ( weight < 0 )
return QStringLiteral(
"100" );
134 if ( weight > 99 )
return QStringLiteral(
"900" );
135 return QString::number( weight * 800 / 99 + 100 );
141 int weight =
str.toInt( &ok );
143 return static_cast< int >( QFont::Normal );
147 if ( weight > 900 )
return 99;
148 if ( weight < 100 )
return 0;
149 return ( weight - 100 ) * 99 / 800;
157 return QStringLiteral(
"no" );
159 return QStringLiteral(
"solid" );
161 return QStringLiteral(
"dash" );
163 return QStringLiteral(
"dot" );
164 case Qt::DashDotLine:
165 return QStringLiteral(
"dash dot" );
166 case Qt::DashDotDotLine:
167 return QStringLiteral(
"dash dot dot" );
169 return QStringLiteral(
"???" );
175 if (
str == QLatin1String(
"no" ) )
return Qt::NoPen;
176 if (
str == QLatin1String(
"solid" ) )
return Qt::SolidLine;
177 if (
str == QLatin1String(
"dash" ) )
return Qt::DashLine;
178 if (
str == QLatin1String(
"dot" ) )
return Qt::DotLine;
179 if (
str == QLatin1String(
"dash dot" ) )
return Qt::DashDotLine;
180 if (
str == QLatin1String(
"dash dot dot" ) )
return Qt::DashDotDotLine;
181 return Qt::SolidLine;
189 return QStringLiteral(
"bevel" );
191 return QStringLiteral(
"miter" );
193 return QStringLiteral(
"round" );
195 return QStringLiteral(
"???" );
201 const QString cleaned =
str.toLower().trimmed();
202 if ( cleaned == QLatin1String(
"bevel" ) )
203 return Qt::BevelJoin;
204 if ( cleaned == QLatin1String(
"miter" ) )
205 return Qt::MiterJoin;
206 if ( cleaned == QLatin1String(
"round" ) )
207 return Qt::RoundJoin;
208 return Qt::BevelJoin;
216 return QStringLiteral(
"bevel" );
218 return QStringLiteral(
"mitre" );
220 return QStringLiteral(
"round" );
228 if (
str == QLatin1String(
"bevel" ) )
return Qt::BevelJoin;
229 if (
str == QLatin1String(
"mitre" ) )
return Qt::MiterJoin;
230 if (
str == QLatin1String(
"round" ) )
return Qt::RoundJoin;
231 return Qt::BevelJoin;
239 return QStringLiteral(
"square" );
241 return QStringLiteral(
"flat" );
243 return QStringLiteral(
"round" );
245 return QStringLiteral(
"???" );
251 if (
str == QLatin1String(
"square" ) )
return Qt::SquareCap;
252 if (
str == QLatin1String(
"flat" ) )
return Qt::FlatCap;
253 if (
str == QLatin1String(
"round" ) )
return Qt::RoundCap;
254 return Qt::SquareCap;
262 return QStringLiteral(
"square" );
264 return QStringLiteral(
"butt" );
266 return QStringLiteral(
"round" );
274 if (
str == QLatin1String(
"square" ) )
return Qt::SquareCap;
275 if (
str == QLatin1String(
"butt" ) )
return Qt::FlatCap;
276 if (
str == QLatin1String(
"round" ) )
return Qt::RoundCap;
277 return Qt::SquareCap;
284 case Qt::SolidPattern :
285 return QStringLiteral(
"solid" );
286 case Qt::HorPattern :
287 return QStringLiteral(
"horizontal" );
288 case Qt::VerPattern :
289 return QStringLiteral(
"vertical" );
290 case Qt::CrossPattern :
291 return QStringLiteral(
"cross" );
292 case Qt::BDiagPattern :
293 return QStringLiteral(
"b_diagonal" );
294 case Qt::FDiagPattern :
295 return QStringLiteral(
"f_diagonal" );
296 case Qt::DiagCrossPattern :
297 return QStringLiteral(
"diagonal_x" );
298 case Qt::Dense1Pattern :
299 return QStringLiteral(
"dense1" );
300 case Qt::Dense2Pattern :
301 return QStringLiteral(
"dense2" );
302 case Qt::Dense3Pattern :
303 return QStringLiteral(
"dense3" );
304 case Qt::Dense4Pattern :
305 return QStringLiteral(
"dense4" );
306 case Qt::Dense5Pattern :
307 return QStringLiteral(
"dense5" );
308 case Qt::Dense6Pattern :
309 return QStringLiteral(
"dense6" );
310 case Qt::Dense7Pattern :
311 return QStringLiteral(
"dense7" );
313 return QStringLiteral(
"no" );
315 return QStringLiteral(
"???" );
321 if (
str == QLatin1String(
"solid" ) )
return Qt::SolidPattern;
322 if (
str == QLatin1String(
"horizontal" ) )
return Qt::HorPattern;
323 if (
str == QLatin1String(
"vertical" ) )
return Qt::VerPattern;
324 if (
str == QLatin1String(
"cross" ) )
return Qt::CrossPattern;
325 if (
str == QLatin1String(
"b_diagonal" ) )
return Qt::BDiagPattern;
326 if (
str == QLatin1String(
"f_diagonal" ) )
return Qt::FDiagPattern;
327 if (
str == QLatin1String(
"diagonal_x" ) )
return Qt::DiagCrossPattern;
328 if (
str == QLatin1String(
"dense1" ) )
return Qt::Dense1Pattern;
329 if (
str == QLatin1String(
"dense2" ) )
return Qt::Dense2Pattern;
330 if (
str == QLatin1String(
"dense3" ) )
return Qt::Dense3Pattern;
331 if (
str == QLatin1String(
"dense4" ) )
return Qt::Dense4Pattern;
332 if (
str == QLatin1String(
"dense5" ) )
return Qt::Dense5Pattern;
333 if (
str == QLatin1String(
"dense6" ) )
return Qt::Dense6Pattern;
334 if (
str == QLatin1String(
"dense7" ) )
return Qt::Dense7Pattern;
335 if (
str == QLatin1String(
"no" ) )
return Qt::NoBrush;
336 return Qt::SolidPattern;
343 case Qt::CrossPattern:
344 return QStringLiteral(
"cross" );
345 case Qt::DiagCrossPattern:
346 return QStringLiteral(
"x" );
353 return QStringLiteral(
"horline" );
355 return QStringLiteral(
"line" );
356 case Qt::BDiagPattern:
357 return QStringLiteral(
"slash" );
358 case Qt::FDiagPattern:
359 return QStringLiteral(
"backslash" );
362 case Qt::Dense1Pattern:
363 case Qt::Dense2Pattern:
364 case Qt::Dense3Pattern:
365 case Qt::Dense4Pattern:
366 case Qt::Dense5Pattern:
367 case Qt::Dense6Pattern:
368 case Qt::Dense7Pattern:
378 if (
str == QLatin1String(
"horline" ) )
return Qt::HorPattern;
379 if (
str == QLatin1String(
"line" ) )
return Qt::VerPattern;
380 if (
str == QLatin1String(
"cross" ) )
return Qt::CrossPattern;
381 if (
str == QLatin1String(
"slash" ) )
return Qt::BDiagPattern;
382 if (
str == QLatin1String(
"backshash" ) )
return Qt::FDiagPattern;
383 if (
str == QLatin1String(
"x" ) )
return Qt::DiagCrossPattern;
385 if (
str.startsWith( QLatin1String(
"brush://" ) ) )
397 QString s = value.toString().toLower().trimmed();
398 if ( s == QLatin1String(
"single" ) )
400 else if ( s == QLatin1String(
"reversed" ) )
402 else if ( s == QLatin1String(
"double" ) )
404 else if ( value.toInt() == 1 )
406 else if ( value.toInt() == 2 )
408 else if ( value.toInt( &intOk ) == 0 && intOk )
422 QString s = value.toString().toLower().trimmed();
423 if ( s == QLatin1String(
"plain" ) )
425 else if ( s == QLatin1String(
"lefthalf" ) )
427 else if ( s == QLatin1String(
"righthalf" ) )
429 else if ( value.toInt() == 1 )
431 else if ( value.toInt() == 2 )
433 else if ( value.toInt( &intOk ) == 0 && intOk )
448 QStringList lst =
str.split(
',' );
449 if ( lst.count() != 2 )
450 return QPointF( 0, 0 );
451 return QPointF( lst[0].toDouble(), lst[1].toDouble() );
459 if ( value.isNull() )
462 if ( value.type() == QVariant::List )
464 const QVariantList list = value.toList();
465 if ( list.size() != 2 )
469 bool convertOk =
false;
470 double x = list.at( 0 ).toDouble( &convertOk );
473 double y = list.at( 1 ).toDouble( &convertOk );
478 return QPointF( x, y );
486 const QStringList list = value.toString().trimmed().split(
',' );
487 if ( list.count() != 2 )
489 bool convertOk =
false;
490 double x = list.at( 0 ).toDouble( &convertOk );
493 double y = list.at( 1 ).toDouble( &convertOk );
498 return QPointF( x, y );
512 QStringList lst =
string.split(
',' );
513 if ( lst.count() != 2 )
514 return QSizeF( 0, 0 );
515 return QSizeF( lst[0].toDouble(), lst[1].toDouble() );
523 if ( value.isNull() )
526 if ( value.type() == QVariant::List )
528 const QVariantList list = value.toList();
529 if ( list.size() != 2 )
533 bool convertOk =
false;
534 double x = list.at( 0 ).toDouble( &convertOk );
537 double y = list.at( 1 ).toDouble( &convertOk );
542 return QSizeF( x, y );
550 const QStringList list = value.toString().trimmed().split(
',' );
551 if ( list.count() != 2 )
553 bool convertOk =
false;
554 double x = list.at( 0 ).toDouble( &convertOk );
557 double y = list.at( 1 ).toDouble( &convertOk );
562 return QSizeF( x, y );
583 if (
str.startsWith( QLatin1String(
"3x:" ) ) )
586 QString chopped =
str.mid( 3 );
587 lst = chopped.split(
',' );
591 lst =
str.split(
',' );
593 if ( lst.count() < 2 )
596 double minScale = lst[0].toDouble();
598 minScale = minScale != 0 ? 1.0 / minScale : 0;
599 double maxScale = lst[1].toDouble();
601 maxScale = maxScale != 0 ? 1.0 / maxScale : 0;
603 if ( lst.count() < 6 )
623 *scaleFactor = 0.001;
624 return QStringLiteral(
"http://www.opengeospatial.org/se/units/metre" );
631 *scaleFactor = 1 / 0.28;
640 if (
str == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
643 *scaleFactor = 1000.0;
646 else if (
str == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
649 *scaleFactor = 304.8;
652 else if (
str == QLatin1String(
"http://www.opengeospatial.org/se/units/pixel" ) )
662 *scaleFactor = 1 / 0.00028;
668 QString vectorString;
669 QVector<qreal>::const_iterator it = v.constBegin();
670 for ( ; it != v.constEnd(); ++it )
672 if ( it != v.constBegin() )
674 vectorString.append(
';' );
676 vectorString.append( QString::number( *it ) );
683 QVector<qreal> resultVector;
685 QStringList realList = s.split(
';' );
686 QStringList::const_iterator it = realList.constBegin();
687 for ( ; it != realList.constEnd(); ++it )
689 resultVector.append( it->toDouble() );
697 QString vectorString;
698 QVector<qreal>::const_iterator it = v.constBegin();
699 for ( ; it != v.constEnd(); ++it )
701 if ( it != v.constBegin() )
703 vectorString.append(
' ' );
705 vectorString.append( QString::number( *it ) );
712 QVector<qreal> resultVector;
714 QStringList realList = s.split(
' ' );
715 QStringList::const_iterator it = realList.constBegin();
716 for ( ; it != realList.constEnd(); ++it )
718 resultVector.append( it->toDouble() );
726 QString encodedValue;
728 switch ( scaleMethod )
731 encodedValue = QStringLiteral(
"diameter" );
734 encodedValue = QStringLiteral(
"area" );
744 if (
str == QLatin1String(
"diameter" ) )
758 if ( s.compare( QLatin1String(
"Lighten" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Lighten;
759 if ( s.compare( QLatin1String(
"Screen" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Screen;
760 if ( s.compare( QLatin1String(
"Dodge" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorDodge;
761 if ( s.compare( QLatin1String(
"Addition" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Plus;
762 if ( s.compare( QLatin1String(
"Darken" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Darken;
763 if ( s.compare( QLatin1String(
"Multiply" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Multiply;
764 if ( s.compare( QLatin1String(
"Burn" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorBurn;
765 if ( s.compare( QLatin1String(
"Overlay" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Overlay;
766 if ( s.compare( QLatin1String(
"SoftLight" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_SoftLight;
767 if ( s.compare( QLatin1String(
"HardLight" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_HardLight;
768 if ( s.compare( QLatin1String(
"Difference" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Difference;
769 if ( s.compare( QLatin1String(
"Subtract" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Exclusion;
770 return QPainter::CompositionMode_SourceOver;
775 return QIcon(
symbolPreviewPixmap( symbol, size, padding,
nullptr,
false,
nullptr, shape ) );
781 QPixmap pixmap( size );
782 pixmap.fill( Qt::transparent );
784 painter.begin( &pixmap );
788 painter.setRenderHint( QPainter::Antialiasing );
797 size.setWidth( size.rwidth() - ( padding * 2 ) );
798 size.setHeight( size.rheight() - ( padding * 2 ) );
799 painter.translate( padding, padding );
809 std::unique_ptr<QgsSymbol> symbol_noDD( symbol->
clone( ) );
811 for (
const auto &layer : layers )
813 for (
int i = 0; i < layer->dataDefinedProperties().count(); ++i )
815 QgsProperty &prop = layer->dataDefinedProperties().property( i );
821 symbol_noDD->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape );
825 std::unique_ptr<QgsSymbol> symbolClone( symbol->
clone( ) );
826 symbolClone->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape );
840 maxBleed = layerMaxBleed > maxBleed ? layerMaxBleed : maxBleed;
850 painter.begin( &picture );
851 painter.setRenderHint( QPainter::Antialiasing );
855 QgsSymbolRenderContext symbolContext( renderContext, units, 1.0,
false, Qgis::SymbolRenderHints(),
nullptr );
856 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
857 layerClone->drawPreviewIcon( symbolContext, size );
864 QPixmap pixmap( size );
865 pixmap.fill( Qt::transparent );
867 painter.begin( &pixmap );
868 painter.setRenderHint( QPainter::Antialiasing );
877 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
878 layerClone->drawPreviewIcon( symbolContext, size );
880 return QIcon( pixmap );
890 QPixmap pixmap( size );
891 pixmap.fill( Qt::transparent );
894 painter.begin( &pixmap );
897 if ( drawTransparentBackground )
898 drawStippledBackground( &painter, QRect( padding, padding, size.width() - padding * 2, size.height() - padding * 2 ) );
906 for (
int i = 0; i < size.width(); i++ )
908 QPen pen( ramp->
color(
static_cast< double >( i ) / size.width() ) );
909 painter.setPen( pen );
910 const int x = flipDirection ? size.width() - i - 1 : i;
911 painter.drawLine( x, 0 + padding, x, size.height() - 1 - padding );
918 for (
int i = 0; i < size.height(); i++ )
920 QPen pen( ramp->
color(
static_cast< double >( i ) / size.height() ) );
921 painter.setPen( pen );
922 const int y = flipDirection ? size.height() - i - 1 : i;
923 painter.drawLine( 0 + padding, y, size.width() - 1 - padding, y );
936 uchar pixDataRGB[] = { 255, 255, 255, 255,
941 QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
943 int width = ( rect.width() < rect.height() ) ?
944 rect.width() / 2.5 : rect.height() / 2.5;
945 QPixmap pix = QPixmap::fromImage( img.scaled( width, width ) );
948 brush.setTexture( pix );
949 painter->fillRect( rect, brush );
954 qreal s = ( markerSize - 1 ) / 2.0;
959 p.setPen( QColor( 50, 100, 120, 200 ) );
960 p.setBrush( QColor( 200, 200, 210, 120 ) );
961 p.drawEllipse( x - s, y - s, s * 2, s * 2 );
964 p.setPen( QColor( 255, 0, 0 ) );
965 p.drawLine( x - s, y + s, x + s, y - s );
966 p.drawLine( x - s, y - s, x + s, y + s );
978 static QPolygonF makeOffsetGeometry(
const QgsPolylineXY &polyline )
980 int i, pointCount = polyline.count();
982 QPolygonF resultLine;
983 resultLine.resize( pointCount );
987 for ( i = 0; i < pointCount; ++i, tempPtr++ )
988 resultLine[i] = QPointF( tempPtr->
x(), tempPtr->
y() );
992 static QList<QPolygonF> makeOffsetGeometry(
const QgsPolygonXY &polygon )
994 QList<QPolygonF> resultGeom;
995 resultGeom.reserve( polygon.size() );
996 for (
int ring = 0; ring < polygon.size(); ++ring )
997 resultGeom.append( makeOffsetGeometry( polygon[ ring ] ) );
1003 QList<QPolygonF> resultLine;
1005 if ( polyline.count() < 2 )
1007 resultLine.append( polyline );
1011 unsigned int i, pointCount = polyline.count();
1014 QPointF *tempPtr = polyline.data();
1015 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1016 tempPolyline[i] =
QgsPointXY( tempPtr->rx(), tempPtr->ry() );
1019 if ( !tempGeometry.
isNull() )
1021 int quadSegments = 0;
1022 double miterLimit = 2.0;
1030 if ( !offsetGeom.
isNull() )
1032 tempGeometry = offsetGeom;
1037 resultLine.append( makeOffsetGeometry( line ) );
1042 resultLine.append( makeOffsetGeometry( tempGeometry.
asPolygon() ) );
1048 resultLine.reserve( tempMPolyline.count() );
1049 for (
int part = 0; part < tempMPolyline.count(); ++part )
1051 resultLine.append( makeOffsetGeometry( tempMPolyline[ part ] ) );
1058 resultLine.reserve( tempMPolygon.count() );
1059 for (
int part = 0; part < tempMPolygon.count(); ++part )
1061 resultLine.append( makeOffsetGeometry( tempMPolygon[ part ] ) );
1069 resultLine.append( polyline );
1079 QDomNode layerNode = element.firstChild();
1081 while ( !layerNode.isNull() )
1083 QDomElement e = layerNode.toElement();
1084 if ( !e.isNull() && e.tagName() != QLatin1String(
"data_defined_properties" ) )
1086 if ( e.tagName() != QLatin1String(
"layer" ) )
1097 QDomElement s = e.firstChildElement( QStringLiteral(
"symbol" ) );
1104 QgsDebugMsg(
"symbol layer refused subsymbol: " + s.attribute(
"name" ) );
1107 layers.append( layer );
1111 layerNode = layerNode.nextSibling();
1114 if ( layers.isEmpty() )
1116 QgsDebugMsg( QStringLiteral(
"no layers for symbol" ) );
1120 QString symbolType = element.attribute( QStringLiteral(
"type" ) );
1123 if ( symbolType == QLatin1String(
"line" ) )
1125 else if ( symbolType == QLatin1String(
"fill" ) )
1127 else if ( symbolType == QLatin1String(
"marker" ) )
1131 QgsDebugMsg(
"unknown symbol type " + symbolType );
1135 if ( element.hasAttribute( QStringLiteral(
"outputUnit" ) ) )
1139 if ( element.hasAttribute( ( QStringLiteral(
"mapUnitScale" ) ) ) )
1142 double oldMin = element.attribute( QStringLiteral(
"mapUnitMinScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1143 mapUnitScale.
minScale = oldMin != 0 ? 1.0 / oldMin : 0;
1144 double oldMax = element.attribute( QStringLiteral(
"mapUnitMaxScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1145 mapUnitScale.
maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
1148 symbol->
setOpacity( element.attribute( QStringLiteral(
"alpha" ), QStringLiteral(
"1.0" ) ).toDouble() );
1149 symbol->
setClipFeaturesToExtent( element.attribute( QStringLiteral(
"clip_to_extent" ), QStringLiteral(
"1" ) ).toInt() );
1150 symbol->
setForceRHR( element.attribute( QStringLiteral(
"force_rhr" ), QStringLiteral(
"0" ) ).toInt() );
1151 Qgis::SymbolFlags flags;
1152 if ( element.attribute( QStringLiteral(
"renderer_should_use_levels" ), QStringLiteral(
"0" ) ).toInt() )
1156 QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1157 if ( !ddProps.isNull() )
1167 QString layerClass = element.attribute( QStringLiteral(
"class" ) );
1168 bool locked = element.attribute( QStringLiteral(
"locked" ) ).toInt();
1169 bool enabled = element.attribute( QStringLiteral(
"enabled" ), QStringLiteral(
"1" ) ).toInt();
1170 int pass = element.attribute( QStringLiteral(
"pass" ) ).toInt();
1189 QDomElement effectElem = element.firstChildElement( QStringLiteral(
"effect" ) );
1190 if ( !effectElem.isNull() )
1198 QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1199 if ( !ddProps.isNull() )
1218 return QStringLiteral(
"line" );
1220 return QStringLiteral(
"marker" );
1222 return QStringLiteral(
"fill" );
1231 QDomElement symEl = doc.createElement( QStringLiteral(
"symbol" ) );
1232 symEl.setAttribute( QStringLiteral(
"type" ), _nameForSymbolType( symbol->
type() ) );
1233 symEl.setAttribute( QStringLiteral(
"name" ), name );
1234 symEl.setAttribute( QStringLiteral(
"alpha" ), QString::number( symbol->
opacity() ) );
1235 symEl.setAttribute( QStringLiteral(
"clip_to_extent" ), symbol->
clipFeaturesToExtent() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1236 symEl.setAttribute( QStringLiteral(
"force_rhr" ), symbol->
forceRHR() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1238 symEl.setAttribute( QStringLiteral(
"renderer_should_use_levels" ), QStringLiteral(
"1" ) );
1242 QDomElement ddProps = doc.createElement( QStringLiteral(
"data_defined_properties" ) );
1244 symEl.appendChild( ddProps );
1250 QDomElement layerEl = doc.createElement( QStringLiteral(
"layer" ) );
1251 layerEl.setAttribute( QStringLiteral(
"class" ), layer->
layerType() );
1252 layerEl.setAttribute( QStringLiteral(
"enabled" ), layer->
enabled() );
1253 layerEl.setAttribute( QStringLiteral(
"locked" ), layer->
isLocked() );
1254 layerEl.setAttribute( QStringLiteral(
"pass" ), layer->
renderingPass() );
1266 QDomElement ddProps = doc.createElement( QStringLiteral(
"data_defined_properties" ) );
1268 layerEl.appendChild( ddProps );
1272 QString subname = QStringLiteral(
"@%1@%2" ).arg( name ).arg( i );
1273 QDomElement subEl =
saveSymbol( subname, subSymbol, doc, context );
1274 layerEl.appendChild( subEl );
1276 symEl.appendChild( layerEl );
1284 QDomDocument doc( QStringLiteral(
"qgis-symbol-definition" ) );
1287 QTextStream stream( &props );
1288 symbolElem.save( stream, -1 );
1294 QList<QgsSymbolLayer *> &layers )
1298 if ( element.isNull() )
1303 QString symbolizerName = element.localName();
1305 if ( symbolizerName == QLatin1String(
"PointSymbolizer" ) )
1308 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1309 if ( graphicElem.isNull() )
1311 QgsDebugMsg( QStringLiteral(
"Graphic element not found in PointSymbolizer" ) );
1347 if ( symbolizerName == QLatin1String(
"LineSymbolizer" ) )
1350 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1351 if ( strokeElem.isNull() )
1353 QgsDebugMsg( QStringLiteral(
"Stroke element not found in LineSymbolizer" ) );
1383 if ( symbolizerName == QLatin1String(
"PolygonSymbolizer" ) )
1386 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1387 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1388 if ( fillElem.isNull() && strokeElem.isNull() )
1390 QgsDebugMsg( QStringLiteral(
"neither Fill nor Stroke element not found in PolygonSymbolizer" ) );
1408 if ( l->
layerType() == QLatin1String(
"SimpleFill" ) || l->
layerType() == QLatin1String(
"SVGFill" ) )
1444 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1445 if ( fillElem.isNull() )
1447 QgsDebugMsg( QStringLiteral(
"Fill element not found" ) );
1467 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1468 if ( strokeElem.isNull() )
1470 QgsDebugMsg( QStringLiteral(
"Stroke element not found" ) );
1486 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1487 if ( graphicElem.isNull() )
1489 QgsDebugMsg( QStringLiteral(
"Graphic element not found" ) );
1509 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1510 if ( graphicElem.isNull() )
1513 QDomElement externalGraphicElem = graphicElem.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
1514 if ( externalGraphicElem.isNull() )
1518 QDomElement formatElem = externalGraphicElem.firstChildElement( QStringLiteral(
"Format" ) );
1519 if ( formatElem.isNull() )
1522 QString format = formatElem.firstChild().nodeValue();
1523 if ( format != QLatin1String(
"image/svg+xml" ) )
1525 QgsDebugMsg(
"unsupported External Graphic format found: " + format );
1530 QDomElement onlineResourceElem = externalGraphicElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1531 QDomElement inlineContentElem = externalGraphicElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1532 if ( !onlineResourceElem.isNull() )
1537 else if ( !inlineContentElem.isNull() )
1550 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1551 if ( graphicElem.isNull() )
1554 QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1555 if ( markElem.isNull() )
1558 QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
1559 return !wellKnownNameElem.isNull();
1565 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1566 if ( graphicElem.isNull() )
1569 QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1570 if ( markElem.isNull() )
1574 QDomElement formatElem = markElem.firstChildElement( QStringLiteral(
"Format" ) );
1575 if ( formatElem.isNull() )
1578 QString format = formatElem.firstChild().nodeValue();
1579 if ( format != QLatin1String(
"ttf" ) )
1581 QgsDebugMsg(
"unsupported Graphic Mark format found: " + format );
1586 QDomElement onlineResourceElem = markElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1587 QDomElement inlineContentElem = markElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1588 if ( !onlineResourceElem.isNull() )
1591 QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
1592 if ( !markIndexElem.isNull() )
1595 else if ( !inlineContentElem.isNull() )
1610 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1611 if ( graphicElem.isNull() )
1615 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
1617 if ( it.key() == QLatin1String(
"widthHeightFactor" ) )
1628 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1629 if ( strokeElem.isNull() )
1632 QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral(
"GraphicStroke" ) );
1633 if ( graphicStrokeElem.isNull() )
1641 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1642 if ( fillElem.isNull() )
1645 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1646 if ( graphicFillElem.isNull() )
1649 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1650 if ( graphicElem.isNull() )
1656 QColor fillColor, strokeColor;
1657 double size, strokeWidth;
1658 Qt::PenStyle strokeStyle;
1659 if ( !
wellKnownMarkerFromSld( graphicElem, name, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
1662 if ( name != QLatin1String(
"horline" ) )
1670 double angle = angleFunc.toDouble( &ok );
1682 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1683 if ( fillElem.isNull() )
1686 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1687 if ( graphicFillElem.isNull() )
1707 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1708 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1712 bool validFill =
false, validStroke =
false;
1717 Qt::BrushStyle fillStyle;
1719 if (
fillFromSld( fillElem, fillStyle, fillColor ) )
1725 Qt::PenStyle strokeStyle;
1726 double strokeWidth = 1.0, dashOffset = 0.0;
1727 QVector<qreal> customDashPattern;
1729 if (
lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth,
1730 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
1733 if ( validFill || validStroke )
1736 map[QStringLiteral(
"name" )] = QStringLiteral(
"square" );
1737 map[QStringLiteral(
"color" )] =
encodeColor( validFill ? fillColor : Qt::transparent );
1738 map[QStringLiteral(
"color_border" )] =
encodeColor( validStroke ? strokeColor : Qt::transparent );
1739 map[QStringLiteral(
"size" )] = QString::number( 6 );
1740 map[QStringLiteral(
"angle" )] = QString::number( 0 );
1741 map[QStringLiteral(
"offset" )] =
encodePoint( QPointF( 0, 0 ) );
1748 bool validFill =
false, validStroke =
false;
1751 QString name, format;
1753 QColor fillColor, strokeColor;
1754 double strokeWidth = 1.0, size = 0.0,
angle = 0.0;
1758 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1759 if ( !graphicFillElem.isNull() )
1762 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1763 if ( !graphicElem.isNull() )
1769 QDomElement graphicChildElem = graphicElem.firstChildElement();
1770 while ( !graphicChildElem.isNull() )
1772 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
1775 QDomElement wellKnownNameElem = graphicChildElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
1776 if ( !wellKnownNameElem.isNull() )
1778 name = wellKnownNameElem.firstChild().nodeValue();
1784 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) || graphicChildElem.localName() == QLatin1String(
"Mark" ) )
1787 QDomElement formatElem = graphicChildElem.firstChildElement( QStringLiteral(
"Format" ) );
1788 if ( formatElem.isNull() )
1791 format = formatElem.firstChild().nodeValue();
1795 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) && format != QLatin1String(
"image/svg+xml" ) )
1800 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format != QLatin1String(
"ttf" ) )
1804 QDomElement onlineResourceElem = graphicChildElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1805 QDomElement inlineContentElem = graphicChildElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1807 if ( !onlineResourceElem.isNull() )
1809 name = onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) );
1811 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format == QLatin1String(
"ttf" ) )
1814 if ( name.startsWith( QLatin1String(
"ttf://" ) ) )
1815 name = name.mid( 6 );
1818 QDomElement markIndexElem = graphicChildElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
1819 if ( markIndexElem.isNull() )
1823 int v = markIndexElem.firstChild().nodeValue().toInt( &ok );
1834 else if ( !inlineContentElem.isNull() )
1844 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
1846 name = QStringLiteral(
"square" );
1853 if ( found && graphicChildElem.localName() == QLatin1String(
"Mark" ) )
1860 Qt::BrushStyle markFillStyle;
1862 QDomElement markFillElem = graphicChildElem.firstChildElement( QStringLiteral(
"Fill" ) );
1863 if (
fillFromSld( markFillElem, markFillStyle, fillColor ) )
1868 Qt::PenStyle strokeStyle;
1869 double strokeWidth = 1.0, dashOffset = 0.0;
1870 QVector<qreal> customDashPattern;
1872 QDomElement markStrokeElem = graphicChildElem.firstChildElement( QStringLiteral(
"Stroke" ) );
1873 if (
lineFromSld( markStrokeElem, strokeStyle, strokeColor, strokeWidth,
1874 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
1881 QDomElement opacityElem = graphicElem.firstChildElement( QStringLiteral(
"Opacity" ) );
1882 if ( !opacityElem.isNull() )
1883 fillColor.setAlpha(
decodeSldAlpha( opacityElem.firstChild().nodeValue() ) );
1885 QDomElement sizeElem = graphicElem.firstChildElement( QStringLiteral(
"Size" ) );
1886 if ( !sizeElem.isNull() )
1889 double v = sizeElem.firstChild().nodeValue().toDouble( &ok );
1898 double v = angleFunc.toDouble( &ok );
1908 if ( validFill || validStroke )
1910 if ( format == QLatin1String(
"image/svg+xml" ) )
1913 map[QStringLiteral(
"name" )] = name;
1914 map[QStringLiteral(
"fill" )] = fillColor.name();
1915 map[QStringLiteral(
"outline" )] = strokeColor.name();
1916 map[QStringLiteral(
"outline-width" )] = QString::number( strokeWidth );
1918 map[QStringLiteral(
"size" )] = QString::number( size );
1920 map[QStringLiteral(
"angle" )] = QString::number(
angle );
1921 if ( !offset.isNull() )
1922 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
1925 else if ( format == QLatin1String(
"ttf" ) )
1928 map[QStringLiteral(
"font" )] = name;
1929 map[QStringLiteral(
"chr" )] = markIndex;
1930 map[QStringLiteral(
"color" )] =
encodeColor( validFill ? fillColor : Qt::transparent );
1932 map[QStringLiteral(
"size" )] = QString::number( size );
1934 map[QStringLiteral(
"angle" )] = QString::number(
angle );
1935 if ( !offset.isNull() )
1936 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
1942 if ( layers.isEmpty() )
1945 layerList << layers;
1952 QString patternName;
1953 switch ( brushStyle )
1958 case Qt::SolidPattern:
1959 if ( color.isValid() )
1962 if ( color.alpha() < 255 )
1967 case Qt::CrossPattern:
1968 case Qt::DiagCrossPattern:
1969 case Qt::HorPattern:
1970 case Qt::VerPattern:
1971 case Qt::BDiagPattern:
1972 case Qt::FDiagPattern:
1973 case Qt::Dense1Pattern:
1974 case Qt::Dense2Pattern:
1975 case Qt::Dense3Pattern:
1976 case Qt::Dense4Pattern:
1977 case Qt::Dense5Pattern:
1978 case Qt::Dense6Pattern:
1979 case Qt::Dense7Pattern:
1984 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( brushStyle ) ) );
1988 QDomElement graphicFillElem = doc.createElement( QStringLiteral(
"se:GraphicFill" ) );
1989 element.appendChild( graphicFillElem );
1991 QDomElement graphicElem = doc.createElement( QStringLiteral(
"se:Graphic" ) );
1992 graphicFillElem.appendChild( graphicElem );
1994 QColor fillColor = patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
1995 QColor strokeColor = !patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
1998 wellKnownMarkerToSld( doc, graphicElem, patternName, fillColor, strokeColor, Qt::SolidLine, -1, -1 );
2005 brushStyle = Qt::SolidPattern;
2006 color = QColor( 128, 128, 128 );
2008 if ( element.isNull() )
2010 brushStyle = Qt::NoBrush;
2015 QDomElement graphicFillElem = element.firstChildElement( QStringLiteral(
"GraphicFill" ) );
2017 if ( graphicFillElem.isNull() )
2020 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2022 QgsDebugMsg( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ) );
2024 if ( it.key() == QLatin1String(
"fill" ) )
2025 color = QColor( it.value() );
2026 else if ( it.key() == QLatin1String(
"fill-opacity" ) )
2032 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
2033 if ( graphicElem.isNull() )
2036 QString patternName = QStringLiteral(
"square" );
2037 QColor fillColor, strokeColor;
2038 double strokeWidth, size;
2039 Qt::PenStyle strokeStyle;
2040 if ( !
wellKnownMarkerFromSld( graphicElem, patternName, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
2044 if ( brushStyle == Qt::NoBrush )
2047 QColor
c = patternName.startsWith( QLatin1String(
"brush://" ) ) ? fillColor : strokeColor;
2056 Qt::PenStyle penStyle,
const QColor &color,
double width,
2057 const Qt::PenJoinStyle *penJoinStyle,
const Qt::PenCapStyle *penCapStyle,
2058 const QVector<qreal> *customDashPattern,
double dashOffset )
2060 QVector<qreal> dashPattern;
2061 const QVector<qreal> *pattern = &dashPattern;
2063 if ( penStyle == Qt::CustomDashLine && !customDashPattern )
2065 element.appendChild( doc.createComment( QStringLiteral(
"WARNING: Custom dash pattern required but not provided. Using default dash pattern." ) ) );
2066 penStyle = Qt::DashLine;
2078 dashPattern.push_back( 4.0 );
2079 dashPattern.push_back( 2.0 );
2082 dashPattern.push_back( 1.0 );
2083 dashPattern.push_back( 2.0 );
2085 case Qt::DashDotLine:
2086 dashPattern.push_back( 4.0 );
2087 dashPattern.push_back( 2.0 );
2088 dashPattern.push_back( 1.0 );
2089 dashPattern.push_back( 2.0 );
2091 case Qt::DashDotDotLine:
2092 dashPattern.push_back( 4.0 );
2093 dashPattern.push_back( 2.0 );
2094 dashPattern.push_back( 1.0 );
2095 dashPattern.push_back( 2.0 );
2096 dashPattern.push_back( 1.0 );
2097 dashPattern.push_back( 2.0 );
2100 case Qt::CustomDashLine:
2101 Q_ASSERT( customDashPattern );
2102 pattern = customDashPattern;
2106 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( penStyle ) ) );
2110 if ( color.isValid() )
2113 if ( color.alpha() < 255 )
2120 else if ( width == 0 )
2130 if ( !pattern->isEmpty() )
2140 Qt::PenStyle &penStyle, QColor &color,
double &width,
2141 Qt::PenJoinStyle *penJoinStyle, Qt::PenCapStyle *penCapStyle,
2142 QVector<qreal> *customDashPattern,
double *dashOffset )
2146 penStyle = Qt::SolidLine;
2147 color = QColor( 0, 0, 0 );
2150 *penJoinStyle = Qt::BevelJoin;
2152 *penCapStyle = Qt::SquareCap;
2153 if ( customDashPattern )
2154 customDashPattern->clear();
2158 if ( element.isNull() )
2160 penStyle = Qt::NoPen;
2166 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2168 QgsDebugMsg( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ) );
2170 if ( it.key() == QLatin1String(
"stroke" ) )
2172 color = QColor( it.value() );
2174 else if ( it.key() == QLatin1String(
"stroke-opacity" ) )
2178 else if ( it.key() == QLatin1String(
"stroke-width" ) )
2181 double w = it.value().toDouble( &ok );
2185 else if ( it.key() == QLatin1String(
"stroke-linejoin" ) && penJoinStyle )
2189 else if ( it.key() == QLatin1String(
"stroke-linecap" ) && penCapStyle )
2193 else if ( it.key() == QLatin1String(
"stroke-dasharray" ) )
2196 if ( !dashPattern.isEmpty() )
2200 bool dashPatternFound =
false;
2202 if ( dashPattern.count() == 2 )
2204 if ( dashPattern.at( 0 ) == 4.0 &&
2205 dashPattern.at( 1 ) == 2.0 )
2207 penStyle = Qt::DashLine;
2208 dashPatternFound =
true;
2210 else if ( dashPattern.at( 0 ) == 1.0 &&
2211 dashPattern.at( 1 ) == 2.0 )
2213 penStyle = Qt::DotLine;
2214 dashPatternFound =
true;
2217 else if ( dashPattern.count() == 4 )
2219 if ( dashPattern.at( 0 ) == 4.0 &&
2220 dashPattern.at( 1 ) == 2.0 &&
2221 dashPattern.at( 2 ) == 1.0 &&
2222 dashPattern.at( 3 ) == 2.0 )
2224 penStyle = Qt::DashDotLine;
2225 dashPatternFound =
true;
2228 else if ( dashPattern.count() == 6 )
2230 if ( dashPattern.at( 0 ) == 4.0 &&
2231 dashPattern.at( 1 ) == 2.0 &&
2232 dashPattern.at( 2 ) == 1.0 &&
2233 dashPattern.at( 3 ) == 2.0 &&
2234 dashPattern.at( 4 ) == 1.0 &&
2235 dashPattern.at( 5 ) == 2.0 )
2237 penStyle = Qt::DashDotDotLine;
2238 dashPatternFound =
true;
2243 if ( !dashPatternFound )
2245 if ( customDashPattern )
2247 penStyle = Qt::CustomDashLine;
2248 *customDashPattern = dashPattern;
2252 QgsDebugMsg( QStringLiteral(
"custom dash pattern required but not provided. Using default dash pattern." ) );
2253 penStyle = Qt::DashLine;
2258 else if ( it.key() == QLatin1String(
"stroke-dashoffset" ) && dashOffset )
2261 double d = it.value().toDouble( &ok );
2271 const QString &path,
const QString &mime,
2272 const QColor &color,
double size )
2274 QDomElement externalGraphicElem = doc.createElement( QStringLiteral(
"se:ExternalGraphic" ) );
2275 element.appendChild( externalGraphicElem );
2284 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2286 element.appendChild( sizeElem );
2291 const QString &path,
const QColor &fillColor,
double size,
const QColor &strokeColor,
double strokeWidth )
2298 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Parametric SVG" ) ) );
2302 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Plain SVG fallback, no parameters" ) ) );
2305 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Well known marker fallback" ) ) );
2311 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2313 graphicElem.appendChild( sizeElem );
2321 if ( fillColor.isValid() )
2323 url.addQueryItem( QStringLiteral(
"fill" ), fillColor.name() );
2324 url.addQueryItem( QStringLiteral(
"fill-opacity" ),
encodeSldAlpha( fillColor.alpha() ) );
2328 url.addQueryItem( QStringLiteral(
"fill" ), QStringLiteral(
"#000000" ) );
2329 url.addQueryItem( QStringLiteral(
"fill-opacity" ), QStringLiteral(
"1" ) );
2331 if ( strokeColor.isValid() )
2333 url.addQueryItem( QStringLiteral(
"outline" ), strokeColor.name() );
2334 url.addQueryItem( QStringLiteral(
"outline-opacity" ),
encodeSldAlpha( strokeColor.alpha() ) );
2338 url.addQueryItem( QStringLiteral(
"outline" ), QStringLiteral(
"#000000" ) );
2339 url.addQueryItem( QStringLiteral(
"outline-opacity" ), QStringLiteral(
"1" ) );
2341 url.addQueryItem( QStringLiteral(
"outline-width" ), QString::number( strokeWidth ) );
2342 QString params = url.toString( QUrl::FullyEncoded );
2343 if ( params.isEmpty() )
2349 return basePath +
"?" + params;
2354 QString &path, QString &mime,
2355 QColor &color,
double &size )
2360 QDomElement externalGraphicElem = element.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
2361 if ( externalGraphicElem.isNull() )
2366 QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2367 if ( !sizeElem.isNull() )
2370 double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2379 const QString &path,
const QString &format,
int *markIndex,
2380 const QColor &color,
double size )
2382 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2383 element.appendChild( markElem );
2389 QDomElement markIndexElem = doc.createElement( QStringLiteral(
"se:MarkIndex" ) );
2390 markIndexElem.appendChild( doc.createTextNode( QString::number( *markIndex ) ) );
2391 markElem.appendChild( markIndexElem );
2395 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2396 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2397 markElem.appendChild( fillElem );
2402 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2404 element.appendChild( sizeElem );
2409 QString &path, QString &format,
int &markIndex,
2410 QColor &color,
double &size )
2418 QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2419 if ( markElem.isNull() )
2424 QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
2425 if ( !markIndexElem.isNull() )
2428 int i = markIndexElem.firstChild().nodeValue().toInt( &ok );
2434 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2435 Qt::BrushStyle b = Qt::SolidPattern;
2440 QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2441 if ( !sizeElem.isNull() )
2444 double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2453 const QString &name,
const QColor &color,
const QColor &strokeColor, Qt::PenStyle strokeStyle,
2454 double strokeWidth,
double size )
2456 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2457 element.appendChild( markElem );
2459 QDomElement wellKnownNameElem = doc.createElement( QStringLiteral(
"se:WellKnownName" ) );
2460 wellKnownNameElem.appendChild( doc.createTextNode( name ) );
2461 markElem.appendChild( wellKnownNameElem );
2464 if ( color.isValid() )
2466 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2467 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2468 markElem.appendChild( fillElem );
2472 if ( strokeColor.isValid() )
2474 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
2475 lineToSld( doc, strokeElem, strokeStyle, strokeColor, strokeWidth );
2476 markElem.appendChild( strokeElem );
2482 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2484 element.appendChild( sizeElem );
2489 QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle,
2490 double &strokeWidth,
double &size )
2494 name = QStringLiteral(
"square" );
2496 strokeColor = QColor( 0, 0, 0 );
2500 QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2501 if ( markElem.isNull() )
2504 QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
2505 if ( !wellKnownNameElem.isNull() )
2507 name = wellKnownNameElem.firstChild().nodeValue();
2508 QgsDebugMsg(
"found Mark with well known name: " + name );
2512 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2513 Qt::BrushStyle b = Qt::SolidPattern;
2518 QDomElement strokeElem = markElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2519 lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth );
2523 QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2524 if ( !sizeElem.isNull() )
2527 double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2537 if ( !rotationFunc.isEmpty() )
2539 QDomElement rotationElem = doc.createElement( QStringLiteral(
"se:Rotation" ) );
2541 element.appendChild( rotationElem );
2547 QDomElement rotationElem = element.firstChildElement( QStringLiteral(
"Rotation" ) );
2548 if ( !rotationElem.isNull() )
2558 if ( !alphaFunc.isEmpty() )
2560 QDomElement opacityElem = doc.createElement( QStringLiteral(
"se:Opacity" ) );
2562 element.appendChild( opacityElem );
2568 QDomElement opacityElem = element.firstChildElement( QStringLiteral(
"Opacity" ) );
2569 if ( !opacityElem.isNull() )
2578 if ( offset.isNull() )
2581 QDomElement displacementElem = doc.createElement( QStringLiteral(
"se:Displacement" ) );
2582 element.appendChild( displacementElem );
2584 QDomElement dispXElem = doc.createElement( QStringLiteral(
"se:DisplacementX" ) );
2585 dispXElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.x(), 2 ) ) );
2587 QDomElement dispYElem = doc.createElement( QStringLiteral(
"se:DisplacementY" ) );
2588 dispYElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.y(), 2 ) ) );
2590 displacementElem.appendChild( dispXElem );
2591 displacementElem.appendChild( dispYElem );
2598 QDomElement anchorElem = doc.createElement( QStringLiteral(
"se:AnchorPoint" ) );
2599 element.appendChild( anchorElem );
2601 QDomElement anchorXElem = doc.createElement( QStringLiteral(
"se:AnchorPointX" ) );
2602 anchorXElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.x() ) ) );
2604 QDomElement anchorYElem = doc.createElement( QStringLiteral(
"se:AnchorPointY" ) );
2605 anchorYElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.y() ) ) );
2607 anchorElem.appendChild( anchorXElem );
2608 anchorElem.appendChild( anchorYElem );
2613 offset = QPointF( 0, 0 );
2615 QDomElement displacementElem = element.firstChildElement( QStringLiteral(
"Displacement" ) );
2616 if ( displacementElem.isNull() )
2619 QDomElement dispXElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementX" ) );
2620 if ( !dispXElem.isNull() )
2623 double offsetX = dispXElem.firstChild().nodeValue().toDouble( &ok );
2625 offset.setX( offsetX );
2628 QDomElement dispYElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementY" ) );
2629 if ( !dispYElem.isNull() )
2632 double offsetY = dispYElem.firstChild().nodeValue().toDouble( &ok );
2634 offset.setY( offsetY );
2641 const QString &label,
const QFont &font,
2642 const QColor &color,
double size )
2644 QDomElement labelElem = doc.createElement( QStringLiteral(
"se:Label" ) );
2645 labelElem.appendChild( doc.createTextNode( label ) );
2646 element.appendChild( labelElem );
2648 QDomElement fontElem = doc.createElement( QStringLiteral(
"se:Font" ) );
2649 element.appendChild( fontElem );
2653 fontElem.appendChild( createSldParameterElement( doc,
"font-style",
encodeSldFontStyle( font.style() ) ) );
2654 fontElem.appendChild( createSldParameterElement( doc,
"font-weight",
encodeSldFontWeight( font.weight() ) ) );
2659 if ( color.isValid() )
2661 QDomElement fillElem = doc.createElement( QStringLiteral(
"Fill" ) );
2662 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2663 element.appendChild( fillElem );
2668 Qt::PenJoinStyle joinStyle,
2669 Qt::PenCapStyle capStyle,
2671 const QVector<qreal> *dashPattern )
2674 penStyle.append(
"PEN(" );
2675 penStyle.append(
"c:" );
2676 penStyle.append(
c.name() );
2677 penStyle.append(
",w:" );
2679 penStyle.append( QString::number( width * mmScaleFactor ) );
2680 penStyle.append(
"mm" );
2683 if ( dashPattern && !dashPattern->isEmpty() )
2685 penStyle.append(
",p:\"" );
2686 QVector<qreal>::const_iterator pIt = dashPattern->constBegin();
2687 for ( ; pIt != dashPattern->constEnd(); ++pIt )
2689 if ( pIt != dashPattern->constBegin() )
2691 penStyle.append(
' ' );
2693 penStyle.append( QString::number( *pIt * mapUnitScaleFactor ) );
2694 penStyle.append(
'g' );
2696 penStyle.append(
'\"' );
2700 penStyle.append(
",cap:" );
2704 penStyle.append(
'p' );
2707 penStyle.append(
'r' );
2711 penStyle.append(
'b' );
2715 penStyle.append(
",j:" );
2716 switch ( joinStyle )
2719 penStyle.append(
'b' );
2722 penStyle.append(
'r' );
2726 penStyle.append(
'm' );
2732 penStyle.append(
",dp:" );
2733 penStyle.append( QString::number( offset * mapUnitScaleFactor ) );
2734 penStyle.append(
'g' );
2737 penStyle.append(
')' );
2744 brushStyle.append(
"BRUSH(" );
2745 brushStyle.append(
"fc:" );
2746 brushStyle.append( fillColor.name() );
2747 brushStyle.append(
')' );
2753 if ( geomFunc.isEmpty() )
2756 QDomElement geometryElem = doc.createElement( QStringLiteral(
"Geometry" ) );
2757 element.appendChild( geometryElem );
2787 QDomElement geometryElem = element.firstChildElement( QStringLiteral(
"Geometry" ) );
2788 if ( geometryElem.isNull() )
2800 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " +
function ) );
2804 if ( !filterElem.isNull() )
2805 element.appendChild( filterElem );
2816 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " +
function ) );
2820 if ( !filterElem.isNull() )
2821 element.appendChild( filterElem );
2828 QDomElement elem = element;
2829 if ( element.tagName() != QLatin1String(
"Filter" ) )
2831 QDomNodeList filterNodes = element.elementsByTagName( QStringLiteral(
"Filter" ) );
2832 if ( !filterNodes.isEmpty() )
2834 elem = filterNodes.at( 0 ).toElement();
2838 if ( elem.isNull() )
2863 const QString &path,
const QString &format )
2867 QDomElement onlineResourceElem = doc.createElement( QStringLiteral(
"se:OnlineResource" ) );
2868 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
2869 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:href" ), url );
2870 element.appendChild( onlineResourceElem );
2872 QDomElement formatElem = doc.createElement( QStringLiteral(
"se:Format" ) );
2873 formatElem.appendChild( doc.createTextNode( format ) );
2874 element.appendChild( formatElem );
2881 QDomElement onlineResourceElem = element.firstChildElement( QStringLiteral(
"OnlineResource" ) );
2882 if ( onlineResourceElem.isNull() )
2885 path = onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) );
2887 QDomElement formatElem = element.firstChildElement( QStringLiteral(
"Format" ) );
2888 if ( formatElem.isNull() )
2891 format = formatElem.firstChild().nodeValue();
2898 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:SvgParameter" ) );
2899 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
2900 nodeElem.appendChild( doc.createTextNode( value ) );
2909 QDomElement paramElem = element.firstChildElement();
2910 while ( !paramElem.isNull() )
2912 if ( paramElem.localName() == QLatin1String(
"SvgParameter" ) || paramElem.localName() == QLatin1String(
"CssParameter" ) )
2914 QString name = paramElem.attribute( QStringLiteral(
"name" ) );
2915 if ( paramElem.firstChild().nodeType() == QDomNode::TextNode )
2917 value = paramElem.firstChild().nodeValue();
2921 if ( paramElem.firstChild().nodeType() == QDomNode::ElementNode &&
2922 paramElem.firstChild().localName() == QLatin1String(
"Literal" ) )
2924 QgsDebugMsg( paramElem.firstChild().localName() );
2925 value = paramElem.firstChild().firstChild().nodeValue();
2929 QgsDebugMsg( QStringLiteral(
"unexpected child of %1" ).arg( paramElem.localName() ) );
2933 if ( !name.isEmpty() && !value.isEmpty() )
2934 params[ name ] = value;
2937 paramElem = paramElem.nextSiblingElement();
2945 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:VendorOption" ) );
2946 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
2947 nodeElem.appendChild( doc.createTextNode( value ) );
2955 QDomElement paramElem = element.firstChildElement( QStringLiteral(
"VendorOption" ) );
2956 while ( !paramElem.isNull() )
2958 QString name = paramElem.attribute( QStringLiteral(
"name" ) );
2959 QString value = paramElem.firstChild().nodeValue();
2961 if ( !name.isEmpty() && !value.isEmpty() )
2962 params[ name ] = value;
2964 paramElem = paramElem.nextSiblingElement( QStringLiteral(
"VendorOption" ) );
2974 if ( newSymbols.type() == QVariant::Map )
2976 return newSymbols.toMap();
2983 QDomElement e = element.firstChildElement();
2984 while ( !e.isNull() )
2986 if ( e.tagName() == QLatin1String(
"prop" ) )
2988 QString propKey = e.attribute( QStringLiteral(
"k" ) );
2989 QString propValue = e.attribute( QStringLiteral(
"v" ) );
2990 props[propKey] = propValue;
2992 e = e.nextSiblingElement();
3007 for ( QVariantMap::iterator it = props.begin(); it != props.end(); ++it )
3009 QDomElement propEl = doc.createElement( QStringLiteral(
"prop" ) );
3010 propEl.setAttribute( QStringLiteral(
"k" ), it.key() );
3011 propEl.setAttribute( QStringLiteral(
"v" ), it.value().toString() );
3012 element.appendChild( propEl );
3022 QDomElement e = element.firstChildElement();
3024 while ( !e.isNull() )
3026 if ( e.tagName() == QLatin1String(
"symbol" ) )
3030 symbols.insert( e.attribute( QStringLiteral(
"name" ) ), symbol );
3036 e = e.nextSiblingElement();
3043 QStringList subsymbols;
3045 for ( QMap<QString, QgsSymbol *>::iterator it = symbols.begin(); it != symbols.end(); ++it )
3047 if ( it.key()[0] !=
'@' )
3051 subsymbols.append( it.key() );
3053 QStringList parts = it.key().split(
'@' );
3054 if ( parts.count() < 3 )
3056 QgsDebugMsg(
"found subsymbol with invalid name: " + it.key() );
3060 QString symname = parts[1];
3061 int symlayer = parts[2].toInt();
3063 if ( !symbols.contains( symname ) )
3065 QgsDebugMsg(
"subsymbol references invalid symbol: " + symname );
3073 QgsDebugMsg(
"subsymbol references invalid symbol layer: " + QString::number( symlayer ) );
3082 QgsDebugMsg(
"symbol layer refused subsymbol: " + it.key() );
3089 for (
int i = 0; i < subsymbols.count(); i++ )
3090 symbols.take( subsymbols[i] );
3097 QDomElement symbolsElem = doc.createElement( tagName );
3100 for ( QMap<QString, QgsSymbol *>::iterator its = symbols.begin(); its != symbols.end(); ++its )
3102 QDomElement symEl =
saveSymbol( its.key(), its.value(), doc, context );
3103 symbolsElem.appendChild( symEl );
3111 qDeleteAll( symbols );
3120 std::unique_ptr< QMimeData >mimeData(
new QMimeData );
3122 QDomDocument symbolDoc;
3124 symbolDoc.appendChild( symbolElem );
3125 mimeData->setText( symbolDoc.toString() );
3128 mimeData->setColorData( symbol->
color() );
3130 return mimeData.release();
3138 QString text = data->text();
3139 if ( !text.isEmpty() )
3144 if ( doc.setContent( text ) )
3146 elem = doc.documentElement();
3148 if ( elem.nodeName() != QLatin1String(
"symbol" ) )
3149 elem = elem.firstChildElement( QStringLiteral(
"symbol" ) );
3160 QString rampType = element.attribute( QStringLiteral(
"type" ) );
3177 QgsDebugMsg(
"unknown colorramp type " + rampType );
3185 QDomElement rampEl = doc.createElement( QStringLiteral(
"colorramp" ) );
3186 rampEl.setAttribute( QStringLiteral(
"type" ), ramp->
type() );
3187 rampEl.setAttribute( QStringLiteral(
"name" ), name );
3195 QVariantMap rampMap;
3197 rampMap.insert( QStringLiteral(
"type" ), ramp->
type() );
3198 rampMap.insert( QStringLiteral(
"name" ), name );
3202 QVariantMap propertyMap;
3203 for (
auto property = properties.constBegin(); property != properties.constEnd(); ++property )
3205 propertyMap.insert( property.key(), property.value() );
3208 rampMap.insert( QStringLiteral(
"properties" ), propertyMap );
3214 QVariantMap rampMap = value.toMap();
3216 QString rampType = rampMap.
value( QStringLiteral(
"type" ) ).toString();
3219 QVariantMap propertyMap = rampMap.value( QStringLiteral(
"properties" ) ).toMap();
3222 for (
auto property = propertyMap.constBegin(); property != propertyMap.constEnd(); ++property )
3224 props.insert( property.key(), property.value().toString() );
3239 QgsDebugMsg(
"unknown colorramp type " + rampType );
3246 if ( !color.isValid() )
3253 return color.name();
3258 QList<QColor> colors;
3261 QStringList components = colorStr.simplified().split( QRegExp(
"(,|\\s)" ) );
3262 QStringList::iterator it = components.begin();
3263 for ( ; it != components.end(); ++it )
3266 if ( result.isValid() )
3271 if ( colors.length() > 0 )
3277 components = colorStr.split( QRegExp(
"(,|\n)" ) );
3278 it = components.begin();
3279 for ( ; it != components.end(); ++it )
3282 if ( result.isValid() )
3287 if ( colors.length() > 0 )
3293 components = colorStr.simplified().split( QString(
' ' ) );
3294 it = components.begin();
3295 for ( ; it != components.end(); ++it )
3298 if ( result.isValid() )
3303 if ( colors.length() > 0 )
3309 components = colorStr.split(
'\n' );
3310 it = components.begin();
3311 for ( ; it != components.end(); ++it )
3314 if ( result.isValid() )
3327 QMimeData *mimeData =
new QMimeData;
3328 mimeData->setColorData( QVariant( color ) );
3329 mimeData->setText( color.name() );
3336 if ( mimeData->hasColor() )
3338 QColor mimeColor = mimeData->colorData().value<QColor>();
3339 if ( mimeColor.isValid() )
3347 if ( mimeData->hasText() )
3351 if ( textColor.isValid() )
3366 if ( data->hasFormat( QStringLiteral(
"text/xml" ) ) )
3369 QByteArray encodedData = data->data( QStringLiteral(
"text/xml" ) );
3370 QDomDocument xmlDoc;
3371 xmlDoc.setContent( encodedData );
3373 QDomElement dragDataElem = xmlDoc.documentElement();
3374 if ( dragDataElem.tagName() == QLatin1String(
"ColorSchemeModelDragData" ) )
3376 QDomNodeList nodeList = dragDataElem.childNodes();
3377 int nChildNodes = nodeList.size();
3378 QDomElement currentElem;
3380 for (
int i = 0; i < nChildNodes; ++i )
3382 currentElem = nodeList.at( i ).toElement();
3383 if ( currentElem.isNull() )
3388 QPair< QColor, QString> namedColor;
3390 namedColor.second = currentElem.attribute( QStringLiteral(
"label" ), QString() );
3392 mimeColors << namedColor;
3397 if ( mimeColors.length() == 0 && data->hasFormat( QStringLiteral(
"application/x-colorobject-list" ) ) )
3400 QByteArray encodedData = data->data( QStringLiteral(
"application/x-colorobject-list" ) );
3401 QDomDocument xmlDoc;
3402 xmlDoc.setContent( encodedData );
3404 QDomNodeList colorsNodes = xmlDoc.elementsByTagName( QStringLiteral(
"colors" ) );
3405 if ( colorsNodes.length() > 0 )
3407 QDomElement colorsElem = colorsNodes.at( 0 ).toElement();
3408 QDomNodeList colorNodeList = colorsElem.childNodes();
3409 int nChildNodes = colorNodeList.size();
3410 QDomElement currentElem;
3412 for (
int i = 0; i < nChildNodes; ++i )
3415 currentElem = colorNodeList.at( i ).toElement();
3416 if ( currentElem.isNull() )
3421 QDomNodeList colorNodes = currentElem.elementsByTagName( QStringLiteral(
"color" ) );
3422 QDomNodeList nameNodes = currentElem.elementsByTagName( QStringLiteral(
"name" ) );
3424 if ( colorNodes.length() > 0 )
3426 QDomElement colorElem = colorNodes.at( 0 ).toElement();
3428 QStringList colorParts = colorElem.text().simplified().split(
' ' );
3429 if ( colorParts.length() < 3 )
3434 int red = colorParts.at( 0 ).toDouble() * 255;
3435 int green = colorParts.at( 1 ).toDouble() * 255;
3436 int blue = colorParts.at( 2 ).toDouble() * 255;
3437 QPair< QColor, QString> namedColor;
3438 namedColor.first = QColor( red, green, blue );
3439 if ( nameNodes.length() > 0 )
3441 QDomElement nameElem = nameNodes.at( 0 ).toElement();
3442 namedColor.second = nameElem.text();
3444 mimeColors << namedColor;
3450 if ( mimeColors.length() == 0 && data->hasText() )
3454 QList< QColor >::iterator it = parsedColors.begin();
3455 for ( ; it != parsedColors.end(); ++it )
3457 mimeColors << qMakePair( *it, QString() );
3461 if ( mimeColors.length() == 0 && data->hasColor() )
3464 QColor mimeColor = data->colorData().value<QColor>();
3465 if ( mimeColor.isValid() )
3467 mimeColors << qMakePair( mimeColor, QString() );
3477 QMimeData *mimeData =
new QMimeData();
3478 QDomDocument xmlDoc;
3479 QDomElement xmlRootElement = xmlDoc.createElement( QStringLiteral(
"ColorSchemeModelDragData" ) );
3480 xmlDoc.appendChild( xmlRootElement );
3482 QgsNamedColorList::const_iterator colorIt = colorList.constBegin();
3483 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3485 QDomElement namedColor = xmlDoc.createElement( QStringLiteral(
"NamedColor" ) );
3487 namedColor.setAttribute( QStringLiteral(
"label" ), ( *colorIt ).second );
3488 xmlRootElement.appendChild( namedColor );
3490 mimeData->setData( QStringLiteral(
"text/xml" ), xmlDoc.toByteArray() );
3498 colorIt = colorList.constBegin();
3499 QStringList colorListString;
3500 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3502 colorListString << ( *colorIt ).first.name();
3504 mimeData->setText( colorListString.join( QLatin1Char(
'\n' ) ) );
3507 if ( colorList.length() > 0 )
3509 mimeData->setColorData( QVariant( colorList.at( 0 ).first ) );
3517 if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3522 QTextStream stream( &file );
3523 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3524 stream <<
"GIMP Palette" << endl;
3526 stream <<
"GIMP Palette" << Qt::endl;
3528 if ( paletteName.isEmpty() )
3530 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3531 stream <<
"Name: QGIS Palette" << endl;
3533 stream <<
"Name: QGIS Palette" << Qt::endl;
3538 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3539 stream <<
"Name: " << paletteName << endl;
3541 stream <<
"Name: " << paletteName << Qt::endl;
3544 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3545 stream <<
"Columns: 4" << endl;
3546 stream <<
'#' << endl;
3548 stream <<
"Columns: 4" << Qt::endl;
3549 stream <<
'#' << Qt::endl;
3552 for ( QgsNamedColorList::ConstIterator colorIt = colors.constBegin(); colorIt != colors.constEnd(); ++colorIt )
3554 QColor color = ( *colorIt ).first;
3555 if ( !color.isValid() )
3559 stream << QStringLiteral(
"%1 %2 %3" ).arg( color.red(), 3 ).arg( color.green(), 3 ).arg( color.blue(), 3 );
3560 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3561 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << endl;
3563 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << Qt::endl;
3575 if ( !file.open( QIODevice::ReadOnly ) )
3578 return importedColors;
3581 QTextStream in( &file );
3583 QString line = in.readLine();
3584 if ( !line.startsWith( QLatin1String(
"GIMP Palette" ) ) )
3587 return importedColors;
3591 while ( !in.atEnd() && !line.startsWith( QLatin1String(
"Name:" ) ) && !line.startsWith(
'#' ) )
3593 line = in.readLine();
3595 if ( line.startsWith( QLatin1String(
"Name:" ) ) )
3597 QRegExp nameRx(
"Name:\\s*(\\S.*)$" );
3598 if ( nameRx.indexIn( line ) != -1 )
3600 name = nameRx.cap( 1 );
3605 while ( !in.atEnd() && !line.startsWith(
'#' ) )
3607 line = in.readLine();
3612 return importedColors;
3616 QRegExp rx(
"^\\s*(\\d+)\\s+(\\d+)\\s+(\\d+)(\\s.*)?$" );
3617 while ( !in.atEnd() )
3619 line = in.readLine();
3620 if ( rx.indexIn( line ) == -1 )
3624 int red = rx.cap( 1 ).toInt();
3625 int green = rx.cap( 2 ).toInt();
3626 int blue = rx.cap( 3 ).toInt();
3627 QColor color = QColor( red, green, blue );
3628 if ( !color.isValid() )
3635 if ( rx.captureCount() > 3 )
3637 label = rx.cap( 4 ).simplified();
3644 importedColors << qMakePair( color, label );
3649 return importedColors;
3662 QRegExp hexColorAlphaRx(
"^\\s*#?([0-9a-fA-F]{6})([0-9a-fA-F]{2})\\s*$" );
3663 int hexColorIndex = hexColorAlphaRx.indexIn( colorStr );
3666 if ( hexColorIndex == -1 && QColor::isValidColor( colorStr ) )
3669 parsedColor.setNamedColor( colorStr );
3670 if ( parsedColor.isValid() )
3672 containsAlpha =
false;
3678 if ( hexColorIndex > -1 )
3680 QString hexColor = hexColorAlphaRx.cap( 1 );
3681 parsedColor.setNamedColor( QStringLiteral(
"#" ) + hexColor );
3683 int alphaHex = hexColorAlphaRx.cap( 2 ).toInt( &alphaOk, 16 );
3685 if ( parsedColor.isValid() && alphaOk )
3687 parsedColor.setAlpha( alphaHex );
3688 containsAlpha =
true;
3696 QRegExp hexColorRx2(
"^\\s*(?:[0-9a-fA-F]{3}){1,2}\\s*$" );
3697 if ( hexColorRx2.indexIn( colorStr ) != -1 )
3700 parsedColor.setNamedColor( QStringLiteral(
"#" ) + colorStr );
3701 if ( parsedColor.isValid() )
3703 containsAlpha =
false;
3710 QRegExp 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*$" );
3711 if ( rgbFormatRx.indexIn( colorStr ) != -1 )
3713 int r = rgbFormatRx.cap( 1 ).toInt();
3714 int g = rgbFormatRx.cap( 2 ).toInt();
3715 int b = rgbFormatRx.cap( 3 ).toInt();
3716 parsedColor.setRgb( r, g, b );
3717 if ( parsedColor.isValid() )
3719 containsAlpha =
false;
3725 const QRegularExpression hslFormatRx(
"^\\s*hsl\\(?\\s*(\\d+)\\s*,\\s*(\\d+)\\s*%\\s*,\\s*(\\d+)\\s*%\\s*\\)?\\s*;?\\s*$" );
3726 QRegularExpressionMatch match = hslFormatRx.match( colorStr );
3727 if ( match.hasMatch() )
3729 int h = match.captured( 1 ).toInt();
3730 int s = match.captured( 2 ).toInt();
3731 int l = match.captured( 3 ).toInt();
3732 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0 );
3733 if ( parsedColor.isValid() )
3735 containsAlpha =
false;
3741 QRegExp 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*$" );
3742 if ( rgbPercentFormatRx.indexIn( colorStr ) != -1 )
3744 int r = std::round( rgbPercentFormatRx.cap( 1 ).toDouble() * 2.55 );
3745 int g = std::round( rgbPercentFormatRx.cap( 2 ).toDouble() * 2.55 );
3746 int b = std::round( rgbPercentFormatRx.cap( 3 ).toDouble() * 2.55 );
3747 parsedColor.setRgb( r, g, b );
3748 if ( parsedColor.isValid() )
3750 containsAlpha =
false;
3756 QRegExp 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*$" );
3757 if ( rgbaFormatRx.indexIn( colorStr ) != -1 )
3759 int r = rgbaFormatRx.cap( 1 ).toInt();
3760 int g = rgbaFormatRx.cap( 2 ).toInt();
3761 int b = rgbaFormatRx.cap( 3 ).toInt();
3762 int a = std::round( rgbaFormatRx.cap( 4 ).toDouble() * 255.0 );
3763 parsedColor.setRgb( r, g, b, a );
3764 if ( parsedColor.isValid() )
3766 containsAlpha =
true;
3772 QRegExp 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*$" );
3773 if ( rgbaPercentFormatRx.indexIn( colorStr ) != -1 )
3775 int r = std::round( rgbaPercentFormatRx.cap( 1 ).toDouble() * 2.55 );
3776 int g = std::round( rgbaPercentFormatRx.cap( 2 ).toDouble() * 2.55 );
3777 int b = std::round( rgbaPercentFormatRx.cap( 3 ).toDouble() * 2.55 );
3778 int a = std::round( rgbaPercentFormatRx.cap( 4 ).toDouble() * 255.0 );
3779 parsedColor.setRgb( r, g, b, a );
3780 if ( parsedColor.isValid() )
3782 containsAlpha =
true;
3788 const QRegularExpression hslaPercentFormatRx(
"^\\s*hsla\\(?\\s*(\\d+)\\s*,\\s*(\\d+)\\s*%\\s*,\\s*(\\d+)\\s*%\\s*,\\s*([\\d\\.]+)\\s*\\)?\\s*;?\\s*$" );
3789 match = hslaPercentFormatRx.match( colorStr );
3790 if ( match.hasMatch() )
3792 int h = match.captured( 1 ).toInt();
3793 int s = match.captured( 2 ).toInt();
3794 int l = match.captured( 3 ).toInt();
3795 int a = std::round( match.captured( 4 ).toDouble() * 255.0 );
3796 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0, a );
3797 if ( parsedColor.isValid() )
3799 containsAlpha =
true;
3816 QImage::Format format = image->format();
3817 if ( format != QImage::Format_ARGB32_Premultiplied && format != QImage::Format_ARGB32 )
3819 QgsDebugMsg( QStringLiteral(
"no alpha channel." ) );
3824 for (
int heightIndex = 0; heightIndex < image->height(); ++heightIndex )
3826 QRgb *scanLine =
reinterpret_cast< QRgb *
>( image->scanLine( heightIndex ) );
3827 for (
int widthIndex = 0; widthIndex < image->width(); ++widthIndex )
3829 myRgb = scanLine[widthIndex];
3830 if ( format == QImage::Format_ARGB32_Premultiplied )
3831 scanLine[widthIndex] = qRgba( opacity * qRed( myRgb ), opacity * qGreen( myRgb ), opacity * qBlue( myRgb ), opacity * qAlpha( myRgb ) );
3833 scanLine[widthIndex] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), opacity * qAlpha( myRgb ) );
3841 int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
3842 int alpha = ( radius < 1 ) ? 16 : ( radius > 17 ) ? 1 : tab[radius - 1];
3844 if ( image.format() != QImage::Format_ARGB32_Premultiplied
3845 && image.format() != QImage::Format_RGB32 )
3847 image = image.convertToFormat( QImage::Format_ARGB32_Premultiplied );
3850 int r1 = rect.top();
3851 int r2 = rect.bottom();
3852 int c1 = rect.left();
3853 int c2 = rect.right();
3855 int bpl = image.bytesPerLine();
3863 i1 = i2 = ( QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3 );
3865 for (
int col = c1; col <= c2; col++ )
3867 p = image.scanLine( r1 ) + col * 4;
3868 for (
int i = i1; i <= i2; i++ )
3869 rgba[i] = p[i] << 4;
3872 for (
int j = r1; j < r2; j++, p += bpl )
3873 for (
int i = i1; i <= i2; i++ )
3874 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
3877 for (
int row = r1; row <= r2; row++ )
3879 p = image.scanLine( row ) + c1 * 4;
3880 for (
int i = i1; i <= i2; i++ )
3881 rgba[i] = p[i] << 4;
3884 for (
int j = c1; j < c2; j++, p += 4 )
3885 for (
int i = i1; i <= i2; i++ )
3886 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
3889 for (
int col = c1; col <= c2; col++ )
3891 p = image.scanLine( r2 ) + col * 4;
3892 for (
int i = i1; i <= i2; i++ )
3893 rgba[i] = p[i] << 4;
3896 for (
int j = r1; j < r2; j++, p -= bpl )
3897 for (
int i = i1; i <= i2; i++ )
3898 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
3901 for (
int row = r1; row <= r2; row++ )
3903 p = image.scanLine( row ) + c2 * 4;
3904 for (
int i = i1; i <= i2; i++ )
3905 rgba[i] = p[i] << 4;
3908 for (
int j = c1; j < c2; j++, p -= 4 )
3909 for (
int i = i1; i <= i2; i++ )
3910 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
3916 if ( alpha != 255 && alpha > 0 )
3920 double alphaFactor = alpha / 255.;
3921 int r = 0, g = 0, b = 0;
3922 rgb.getRgb( &r, &g, &b );
3927 rgb.setRgb( r, g, b, alpha );
3929 else if ( alpha == 0 )
3931 rgb.setRgb( 0, 0, 0, 0 );
3940 if ( !simpleFill || !simpleLine )
3964 if ( simpleLine->
offset() )
3982 if ( order == Qt::AscendingOrder )
3996 double dx = directionPoint.x() - startPoint.x();
3997 double dy = directionPoint.y() - startPoint.y();
3998 double length = std::sqrt( dx * dx + dy * dy );
3999 double scaleFactor = distance / length;
4000 return QPointF( startPoint.x() + dx * scaleFactor, startPoint.y() + dy * scaleFactor );
4010 for (
int i = 0; i < svgPaths.size(); i++ )
4012 QDir dir( svgPaths[i] );
4013 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4014 for (
const QString &item : svgSubPaths )
4016 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4019 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4020 for (
const QString &item : svgFiles )
4023 list.append( dir.path() +
'/' + item );
4035 QStringList svgPaths;
4036 svgPaths.append( directory );
4038 for (
int i = 0; i < svgPaths.size(); i++ )
4040 QDir dir( svgPaths[i] );
4041 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
4042 for (
const QString &item : svgSubPaths )
4044 svgPaths.insert( i + 1, dir.path() +
'/' + item );
4047 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
4048 for (
const QString &item : svgFiles )
4050 list.append( dir.path() +
'/' + item );
4062 if ( n.startsWith( QLatin1String(
"base64:" ) ) )
4066 if ( QFileInfo::exists( n ) )
4067 return QFileInfo( n ).canonicalFilePath();
4071 if ( name.contains( QLatin1String(
"://" ) ) )
4074 if ( url.isValid() && !url.scheme().isEmpty() )
4076 if ( url.scheme().compare( QLatin1String(
"file" ), Qt::CaseInsensitive ) == 0 )
4079 name = url.toLocalFile();
4080 if ( QFile( name ).exists() )
4082 return QFileInfo( name ).canonicalFilePath();
4096 for (
int i = 0; i < svgPaths.size(); i++ )
4098 QString svgPath = svgPaths[i];
4099 if ( svgPath.endsWith( QChar(
'/' ) ) )
4110 QString myLocalPath = svgPath + QDir::separator() + name;
4113 if ( QFile( myLocalPath ).exists() )
4116 return QFileInfo( myLocalPath ).canonicalFilePath();
4120 return pathResolver.
readPath( name );
4128 if ( p.startsWith( QLatin1String(
"base64:" ) ) )
4131 if ( !QFileInfo::exists( p ) )
4134 QString path = QFileInfo( p ).canonicalFilePath();
4138 bool isInSvgPaths =
false;
4139 for (
int i = 0; i < svgPaths.size(); i++ )
4141 QString dir = QFileInfo( svgPaths[i] ).canonicalFilePath();
4143 if ( !dir.isEmpty() && path.startsWith( dir ) )
4145 path = path.mid( dir.size() + 1 );
4146 isInSvgPaths =
true;
4161 double cx = 0, cy = 0;
4162 double area, sum = 0;
4163 for (
int i = points.count() - 1, j = 0; j < points.count(); i = j++ )
4165 const QPointF &p1 = points[i];
4166 const QPointF &p2 = points[j];
4167 area = p1.x() * p2.y() - p1.y() * p2.x();
4169 cx += ( p1.x() + p2.x() ) * area;
4170 cy += ( p1.y() + p2.y() ) * area;
4177 if ( points.count() >= 2 )
4178 return QPointF( ( points[0].x() + points[1].x() ) / 2, ( points[0].y() + points[1].y() ) / 2 );
4179 else if ( points.count() == 1 )
4187 return QPointF( cx, cy );
4194 if ( ( rings && rings->count() > 0 ) || !
pointInPolygon( points, centroid ) )
4196 unsigned int i, pointCount = points.count();
4198 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( points[i].x(), points[i].y() );
4204 for (
auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
4206 pointCount = ( *ringIt ).count();
4208 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( ( *ringIt )[i].x(), ( *ringIt )[i].y() );
4214 if ( !pointOnSurfaceGeom.
isNull() )
4217 centroid.
setX( point.
x() );
4218 centroid.setY( point.
y() );
4223 return QPointF( centroid.x(), centroid.y() );
4228 bool inside =
false;
4230 double x = point.x();
4231 double y = point.y();
4233 for (
int i = 0, j = points.count() - 1; i < points.count(); i++ )
4235 const QPointF &p1 = points[i];
4236 const QPointF &p2 = points[j];
4241 if ( ( p1.y() < y && p2.y() >= y ) || ( p2.y() < y && p1.y() >= y ) )
4243 if ( p1.x() + ( y - p1.y() ) / ( p2.y() - p1.y() ) * ( p2.x() - p1.x() ) <= x )
4254 if ( polyline.size() < 2 )
4257 double totalLength = 0;
4258 auto it = polyline.begin();
4260 for ( ; it != polyline.end(); ++it )
4263 const double segmentLength = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4264 totalLength += segmentLength;
4272 if ( polyline.size() < 2 )
4275 double totalLength = 0;
4276 auto it = polyline.begin();
4278 std::vector< double > segmentLengths( polyline.size() - 1 );
4279 auto segmentLengthIt = segmentLengths.begin();
4280 for ( ; it != polyline.end(); ++it )
4283 *segmentLengthIt = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4284 totalLength += *segmentLengthIt;
4290 if ( startOffset >= 0 && totalLength <= startOffset )
4292 if ( endOffset < 0 && totalLength <= -endOffset )
4295 const double startDistance = startOffset < 0 ? totalLength + startOffset : startOffset;
4296 const double endDistance = endOffset <= 0 ? totalLength + endOffset : endOffset;
4297 QPolygonF substringPoints;
4298 substringPoints.reserve( polyline.size() );
4300 it = polyline.begin();
4301 segmentLengthIt = segmentLengths.begin();
4304 bool foundStart =
false;
4305 if (
qgsDoubleNear( startDistance, 0.0 ) || startDistance < 0 )
4307 substringPoints << p1;
4311 double distanceTraversed = 0;
4312 for ( ; it != polyline.end(); ++it )
4315 if ( distanceTraversed < startDistance && distanceTraversed + *segmentLengthIt > startDistance )
4318 const double distanceToStart = startDistance - distanceTraversed;
4319 double startX, startY;
4321 substringPoints << QPointF( startX, startY );
4324 if ( foundStart && ( distanceTraversed + *segmentLengthIt > endDistance ) )
4327 const double distanceToEnd = endDistance - distanceTraversed;
4330 if ( substringPoints.last() != QPointF( endX, endY ) )
4331 substringPoints << QPointF( endX, endY );
4333 else if ( foundStart )
4335 if ( substringPoints.last() != QPointF( p2.x(), p2.y() ) )
4336 substringPoints << QPointF( p2.x(), p2.y() );
4339 distanceTraversed += *segmentLengthIt;
4340 if ( distanceTraversed > endDistance )
4347 if ( ( substringPoints.size() < 2 ) || ( substringPoints.size() == 2 && substringPoints.at( 0 ) == substringPoints.at( 1 ) ) )
4350 return substringPoints;
4355 double vertexAngle = M_PI - ( std::atan2( p3.y() - p2.y(), p3.x() - p2.x() ) - std::atan2( p2.y() - p1.y(), p2.x() - p1.x() ) );
4359 return vertexAngle < M_PI * 135.0 / 180.0 || vertexAngle > M_PI * 225.0 / 180.0;
4364 target.reserve( target.size() + line.size() );
4365 for (
const QPointF &pt : line )
4367 if ( !target.empty() && target.last() == pt )
4376 if ( fieldOrExpression.isEmpty() )
4411 QList<double> breaks;
4414 breaks.append( maximum );
4418 int minimumCount =
static_cast< int >( classes ) / 3;
4419 double shrink = 0.75;
4420 double highBias = 1.5;
4421 double adjustBias = 0.5 + 1.5 * highBias;
4422 int divisions = classes;
4423 double h = highBias;
4426 double dx = maximum - minimum;
4436 cell = std::max( std::fabs( minimum ), std::fabs( maximum ) );
4437 if ( adjustBias >= 1.5 * h + 0.5 )
4439 U = 1 + ( 1.0 / ( 1 + h ) );
4443 U = 1 + ( 1.5 / ( 1 + adjustBias ) );
4445 small = dx < ( cell * U * std::max( 1, divisions ) * 1e-07 * 3.0 );
4452 cell = 9 + cell / 10;
4453 cell = cell * shrink;
4455 if ( minimumCount > 1 )
4457 cell = cell / minimumCount;
4463 if ( divisions > 1 )
4465 cell = cell / divisions;
4468 if ( cell < 20 * 1e-07 )
4473 double base = std::pow( 10.0, std::floor( std::log10( cell ) ) );
4475 if ( ( 2 * base ) - cell < h * ( cell - unit ) )
4478 if ( ( 5 * base ) - cell < adjustBias * ( cell - unit ) )
4481 if ( ( 10.0 * base ) - cell < h * ( cell - unit ) )
4488 int start = std::floor( minimum / unit + 1e-07 );
4489 int end = std::ceil( maximum / unit - 1e-07 );
4492 while ( start * unit > minimum + ( 1e-07 * unit ) )
4496 while ( end * unit < maximum - ( 1e-07 * unit ) )
4500 QgsDebugMsg( QStringLiteral(
"pretty classes: %1" ).arg( end ) );
4504 int k = std::floor( 0.5 + end - start );
4505 if ( k < minimumCount )
4507 k = minimumCount - k;
4511 start = start - k / 2 + k % 2;
4515 start = start - k / 2;
4516 end = end + k / 2 + k % 2;
4519 double minimumBreak = start * unit;
4521 int count = end - start;
4523 breaks.reserve( count );
4524 for (
int i = 1; i < count + 1; i++ )
4526 breaks.append( minimumBreak + i * unit );
4529 if ( breaks.isEmpty() )
4532 if ( breaks.first() < minimum )
4534 breaks[0] = minimum;
4536 if ( breaks.last() > maximum )
4538 breaks[breaks.count() - 1] = maximum;
4543 if ( minimum < 0.0 && maximum > 0.0 )
4545 QList<double> breaksMinusZero;
4546 for (
int i = 0; i < breaks.count(); i++ )
4548 breaksMinusZero.append( breaks[i] - 0.0 );
4551 for (
int i = 1; i < breaks.count(); i++ )
4553 if ( std::abs( breaksMinusZero[i] ) < std::abs( breaksMinusZero[i - 1] ) )
4556 breaks[posOfMin] = 0.0;
4565 bool roundToUnit =
false;
4568 if ( props.contains( QStringLiteral(
"uomScale" ) ) )
4571 scale = props.value( QStringLiteral(
"uomScale" ) ).toDouble( &ok );
4580 if ( props.value( QStringLiteral(
"uom" ) ) == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
4605 scale = 1 / 0.28 * 25.4;
4629 double rescaled = size * scale;
4634 rescaled = std::round( rescaled );
4641 double x =
rescaleUom( point.x(), unit, props );
4642 double y =
rescaleUom( point.y(), unit, props );
4643 return QPointF( x, y );
4648 QVector<qreal> result;
4649 QVector<qreal>::const_iterator it = array.constBegin();
4650 for ( ; it != array.constEnd(); ++it )
4652 result.append(
rescaleUom( *it, unit, props ) );
4659 if ( !props.value( QStringLiteral(
"scaleMinDenom" ), QString() ).toString().isEmpty() )
4661 QDomElement scaleMinDenomElem = doc.createElement( QStringLiteral(
"se:MinScaleDenominator" ) );
4662 scaleMinDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMinDenom" ) ).toString().toDouble() ) ) );
4663 ruleElem.appendChild( scaleMinDenomElem );
4666 if ( !props.value( QStringLiteral(
"scaleMaxDenom" ), QString() ).toString().isEmpty() )
4668 QDomElement scaleMaxDenomElem = doc.createElement( QStringLiteral(
"se:MaxScaleDenominator" ) );
4669 scaleMaxDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMaxDenom" ) ).toString().toDouble() ) ) );
4670 ruleElem.appendChild( scaleMaxDenomElem );
4679 double parentScaleMinDenom = props.value( QStringLiteral(
"scaleMinDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
4680 if ( !ok || parentScaleMinDenom <= 0 )
4681 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( mScaleMinDenom );
4683 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( std::max( parentScaleMinDenom, mScaleMinDenom ) );
4689 double parentScaleMaxDenom = props.value( QStringLiteral(
"scaleMaxDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
4690 if ( !ok || parentScaleMaxDenom <= 0 )
4691 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( mScaleMaxDenom );
4693 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( std::min( parentScaleMaxDenom, mScaleMaxDenom ) );
4701 if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
4703 scale = 1.0 / 0.00028;
4705 else if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
4707 scale = 304.8 / 0.28;
4714 return size * scale;
4722 SymbolLayerVisitor(
const QSet<QgsSymbolLayerId> &layerIds )
4723 : mSymbolLayerIds( layerIds )
4736 void visitSymbol(
const QgsSymbol *symbol,
const QString &identifier, QVector<int> rootPath )
4740 QVector<int> indexPath = rootPath;
4741 indexPath.append( idx );
4743 if ( mSymbolLayerIds.contains(
QgsSymbolLayerId( mCurrentRuleKey + identifier, indexPath ) ) )
4745 mSymbolLayers.insert( sl );
4750 visitSymbol( subSymbol, identifier, indexPath );
4759 if ( symbolEntity->symbol() )
4761 visitSymbol( symbolEntity->symbol(), leaf.
identifier, {} );
4767 QString mCurrentRuleKey;
4768 const QSet<QgsSymbolLayerId> &mSymbolLayerIds;
4769 QSet<const QgsSymbolLayer *> mSymbolLayers;
4772 SymbolLayerVisitor visitor( symbolLayerIds );
4773 renderer->
accept( &visitor );
4774 return visitor.mSymbolLayers;
4779 if ( !s || !context )
4789 size = markerSymbol->
size( *context );
4791 else if ( lineSymbol )
4793 size = lineSymbol->
width( *context );
4802 if ( minSize > 0 && size < minSize )
4806 else if ( maxSize > 0 && size > maxSize )
4824 else if ( lineSymbol )
4838 QMap<QString, QgsProperty>::const_iterator paramIt = propertiesMap.constBegin();
4839 for ( ; paramIt != propertiesMap.constEnd(); ++paramIt )
4841 properties.insert( paramIt.key(), paramIt.value().valueAsString( context ) );
ScaleMethod
Scale methods.
@ ScaleDiameter
Calculate scale by the diameter.
@ ScaleArea
Calculate scale by the area.
@ 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.
@ JoinStyleMiter
Use mitered joins.
QgsMultiPolygonXY asMultiPolygon() const
Returns the contents of the geometry as a multi-polygon.
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.
OperationResult addRing(const QVector< QgsPointXY > &ring)
Adds a new ring to this geometry.
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.
@ CapFlat
Flat cap (in line with start/end of line)
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 QgsPolygon.
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...
QgsGeometry offsetCurve(double distance, int segments, JoinStyle joinStyle, double miterLimit) const
Returns an offset line at a given distance and side from an input line.
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 x value of the point.
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 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(Flag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
@ RenderSymbolPreview
The render is for a symbol preview only and map based properties may not be available,...
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 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 QPicture symbolLayerPreviewPicture(const QgsSymbolLayer *layer, QgsUnitTypes::RenderUnit units, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale())
Draws a symbol layer preview to a QPicture.
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 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)
VertexMarkerType
Editing vertex markers.
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 QIcon symbolLayerPreviewIcon(const QgsSymbolLayer *layer, QgsUnitTypes::RenderUnit u, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale())
Draws a symbol layer preview to an icon.
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 void drawVertexMarker(double x, double y, QPainter &p, QgsSymbolLayerUtils::VertexMarkerType type, int markerSize)
Draws a vertex symbol at (painter) coordinates x, y.
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 QString encodeRealVector(const QVector< qreal > &v)
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.
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.
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)
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.