42 #include <QDomDocument>
44 #include <QDomElement>
53 #include <QRegularExpression>
55 #define POINTS_TO_MM 2.83464567
59 return QStringLiteral(
"%1,%2,%3,%4" ).arg( color.red() ).arg( color.green() ).arg( color.blue() ).arg( color.alpha() );
64 const QStringList lst = str.split(
',' );
65 if ( lst.count() < 3 )
69 int red, green, blue, alpha;
71 green = lst[1].toInt();
72 blue = lst[2].toInt();
74 if ( lst.count() > 3 )
76 alpha = lst[3].toInt();
78 return QColor( red, green, blue, alpha );
83 return QString::number( alpha / 255.0,
'g', 2 );
89 double alpha = str.toDouble( &ok );
90 if ( !ok || alpha > 1 )
101 case QFont::StyleNormal:
102 return QStringLiteral(
"normal" );
103 case QFont::StyleItalic:
104 return QStringLiteral(
"italic" );
105 case QFont::StyleOblique:
106 return QStringLiteral(
"oblique" );
114 if ( str == QLatin1String(
"normal" ) )
return QFont::StyleNormal;
115 if ( str == QLatin1String(
"italic" ) )
return QFont::StyleItalic;
116 if ( str == QLatin1String(
"oblique" ) )
return QFont::StyleOblique;
117 return QFont::StyleNormal;
122 if ( weight == 50 )
return QStringLiteral(
"normal" );
123 if ( weight == 75 )
return QStringLiteral(
"bold" );
127 if ( weight < 0 )
return QStringLiteral(
"100" );
128 if ( weight > 99 )
return QStringLiteral(
"900" );
129 return QString::number( weight * 800 / 99 + 100 );
135 int weight = str.toInt( &ok );
137 return static_cast< int >( QFont::Normal );
141 if ( weight > 900 )
return 99;
142 if ( weight < 100 )
return 0;
143 return ( weight - 100 ) * 99 / 800;
151 return QStringLiteral(
"no" );
153 return QStringLiteral(
"solid" );
155 return QStringLiteral(
"dash" );
157 return QStringLiteral(
"dot" );
158 case Qt::DashDotLine:
159 return QStringLiteral(
"dash dot" );
160 case Qt::DashDotDotLine:
161 return QStringLiteral(
"dash dot dot" );
163 return QStringLiteral(
"???" );
169 if ( str == QLatin1String(
"no" ) )
return Qt::NoPen;
170 if ( str == QLatin1String(
"solid" ) )
return Qt::SolidLine;
171 if ( str == QLatin1String(
"dash" ) )
return Qt::DashLine;
172 if ( str == QLatin1String(
"dot" ) )
return Qt::DotLine;
173 if ( str == QLatin1String(
"dash dot" ) )
return Qt::DashDotLine;
174 if ( str == QLatin1String(
"dash dot dot" ) )
return Qt::DashDotDotLine;
175 return Qt::SolidLine;
183 return QStringLiteral(
"bevel" );
185 return QStringLiteral(
"miter" );
187 return QStringLiteral(
"round" );
189 return QStringLiteral(
"???" );
195 const QString cleaned = str.toLower().trimmed();
196 if ( cleaned == QLatin1String(
"bevel" ) )
197 return Qt::BevelJoin;
198 if ( cleaned == QLatin1String(
"miter" ) )
199 return Qt::MiterJoin;
200 if ( cleaned == QLatin1String(
"round" ) )
201 return Qt::RoundJoin;
202 return Qt::BevelJoin;
210 return QStringLiteral(
"bevel" );
212 return QStringLiteral(
"mitre" );
214 return QStringLiteral(
"round" );
222 if ( str == QLatin1String(
"bevel" ) )
return Qt::BevelJoin;
223 if ( str == QLatin1String(
"mitre" ) )
return Qt::MiterJoin;
224 if ( str == QLatin1String(
"round" ) )
return Qt::RoundJoin;
225 return Qt::BevelJoin;
233 return QStringLiteral(
"square" );
235 return QStringLiteral(
"flat" );
237 return QStringLiteral(
"round" );
239 return QStringLiteral(
"???" );
245 if ( str == QLatin1String(
"square" ) )
return Qt::SquareCap;
246 if ( str == QLatin1String(
"flat" ) )
return Qt::FlatCap;
247 if ( str == QLatin1String(
"round" ) )
return Qt::RoundCap;
248 return Qt::SquareCap;
256 return QStringLiteral(
"square" );
258 return QStringLiteral(
"butt" );
260 return QStringLiteral(
"round" );
268 if ( str == QLatin1String(
"square" ) )
return Qt::SquareCap;
269 if ( str == QLatin1String(
"butt" ) )
return Qt::FlatCap;
270 if ( str == QLatin1String(
"round" ) )
return Qt::RoundCap;
271 return Qt::SquareCap;
278 case Qt::SolidPattern :
279 return QStringLiteral(
"solid" );
280 case Qt::HorPattern :
281 return QStringLiteral(
"horizontal" );
282 case Qt::VerPattern :
283 return QStringLiteral(
"vertical" );
284 case Qt::CrossPattern :
285 return QStringLiteral(
"cross" );
286 case Qt::BDiagPattern :
287 return QStringLiteral(
"b_diagonal" );
288 case Qt::FDiagPattern :
289 return QStringLiteral(
"f_diagonal" );
290 case Qt::DiagCrossPattern :
291 return QStringLiteral(
"diagonal_x" );
292 case Qt::Dense1Pattern :
293 return QStringLiteral(
"dense1" );
294 case Qt::Dense2Pattern :
295 return QStringLiteral(
"dense2" );
296 case Qt::Dense3Pattern :
297 return QStringLiteral(
"dense3" );
298 case Qt::Dense4Pattern :
299 return QStringLiteral(
"dense4" );
300 case Qt::Dense5Pattern :
301 return QStringLiteral(
"dense5" );
302 case Qt::Dense6Pattern :
303 return QStringLiteral(
"dense6" );
304 case Qt::Dense7Pattern :
305 return QStringLiteral(
"dense7" );
307 return QStringLiteral(
"no" );
309 return QStringLiteral(
"???" );
315 if ( str == QLatin1String(
"solid" ) )
return Qt::SolidPattern;
316 if ( str == QLatin1String(
"horizontal" ) )
return Qt::HorPattern;
317 if ( str == QLatin1String(
"vertical" ) )
return Qt::VerPattern;
318 if ( str == QLatin1String(
"cross" ) )
return Qt::CrossPattern;
319 if ( str == QLatin1String(
"b_diagonal" ) )
return Qt::BDiagPattern;
320 if ( str == QLatin1String(
"f_diagonal" ) )
return Qt::FDiagPattern;
321 if ( str == QLatin1String(
"diagonal_x" ) )
return Qt::DiagCrossPattern;
322 if ( str == QLatin1String(
"dense1" ) )
return Qt::Dense1Pattern;
323 if ( str == QLatin1String(
"dense2" ) )
return Qt::Dense2Pattern;
324 if ( str == QLatin1String(
"dense3" ) )
return Qt::Dense3Pattern;
325 if ( str == QLatin1String(
"dense4" ) )
return Qt::Dense4Pattern;
326 if ( str == QLatin1String(
"dense5" ) )
return Qt::Dense5Pattern;
327 if ( str == QLatin1String(
"dense6" ) )
return Qt::Dense6Pattern;
328 if ( str == QLatin1String(
"dense7" ) )
return Qt::Dense7Pattern;
329 if ( str == QLatin1String(
"no" ) )
return Qt::NoBrush;
330 return Qt::SolidPattern;
337 case Qt::CrossPattern:
338 return QStringLiteral(
"cross" );
339 case Qt::DiagCrossPattern:
340 return QStringLiteral(
"x" );
347 return QStringLiteral(
"horline" );
349 return QStringLiteral(
"line" );
350 case Qt::BDiagPattern:
351 return QStringLiteral(
"slash" );
352 case Qt::FDiagPattern:
353 return QStringLiteral(
"backslash" );
356 case Qt::Dense1Pattern:
357 case Qt::Dense2Pattern:
358 case Qt::Dense3Pattern:
359 case Qt::Dense4Pattern:
360 case Qt::Dense5Pattern:
361 case Qt::Dense6Pattern:
362 case Qt::Dense7Pattern:
372 if ( str == QLatin1String(
"horline" ) )
return Qt::HorPattern;
373 if ( str == QLatin1String(
"line" ) )
return Qt::VerPattern;
374 if ( str == QLatin1String(
"cross" ) )
return Qt::CrossPattern;
375 if ( str == QLatin1String(
"slash" ) )
return Qt::BDiagPattern;
376 if ( str == QLatin1String(
"backshash" ) )
return Qt::FDiagPattern;
377 if ( str == QLatin1String(
"x" ) )
return Qt::DiagCrossPattern;
379 if ( str.startsWith( QLatin1String(
"brush://" ) ) )
391 QString s = value.toString().toLower().trimmed();
392 if ( s == QLatin1String(
"single" ) )
394 else if ( s == QLatin1String(
"reversed" ) )
396 else if ( s == QLatin1String(
"double" ) )
398 else if ( value.toInt() == 1 )
400 else if ( value.toInt() == 2 )
402 else if ( value.toInt( &intOk ) == 0 && intOk )
416 QString s = value.toString().toLower().trimmed();
417 if ( s == QLatin1String(
"plain" ) )
419 else if ( s == QLatin1String(
"lefthalf" ) )
421 else if ( s == QLatin1String(
"righthalf" ) )
423 else if ( value.toInt() == 1 )
425 else if ( value.toInt() == 2 )
427 else if ( value.toInt( &intOk ) == 0 && intOk )
442 QStringList lst = str.split(
',' );
443 if ( lst.count() != 2 )
444 return QPointF( 0, 0 );
445 return QPointF( lst[0].toDouble(), lst[1].toDouble() );
453 if ( value.isNull() )
456 if ( value.type() == QVariant::List )
458 const QVariantList list = value.toList();
459 if ( list.size() != 2 )
463 bool convertOk =
false;
464 double x = list.at( 0 ).toDouble( &convertOk );
467 double y = list.at( 1 ).toDouble( &convertOk );
472 return QPointF( x, y );
480 const QStringList list = value.toString().trimmed().split(
',' );
481 if ( list.count() != 2 )
483 bool convertOk =
false;
484 double x = list.at( 0 ).toDouble( &convertOk );
487 double y = list.at( 1 ).toDouble( &convertOk );
492 return QPointF( x, y );
506 QStringList lst =
string.split(
',' );
507 if ( lst.count() != 2 )
508 return QSizeF( 0, 0 );
509 return QSizeF( lst[0].toDouble(), lst[1].toDouble() );
517 if ( value.isNull() )
520 if ( value.type() == QVariant::List )
522 const QVariantList list = value.toList();
523 if ( list.size() != 2 )
527 bool convertOk =
false;
528 double x = list.at( 0 ).toDouble( &convertOk );
531 double y = list.at( 1 ).toDouble( &convertOk );
536 return QSizeF( x, y );
544 const QStringList list = value.toString().trimmed().split(
',' );
545 if ( list.count() != 2 )
547 bool convertOk =
false;
548 double x = list.at( 0 ).toDouble( &convertOk );
551 double y = list.at( 1 ).toDouble( &convertOk );
556 return QSizeF( x, y );
577 if ( str.startsWith( QLatin1String(
"3x:" ) ) )
580 QString chopped = str.mid( 3 );
581 lst = chopped.split(
',' );
585 lst = str.split(
',' );
587 if ( lst.count() < 2 )
590 double minScale = lst[0].toDouble();
592 minScale = minScale != 0 ? 1.0 / minScale : 0;
593 double maxScale = lst[1].toDouble();
595 maxScale = maxScale != 0 ? 1.0 / maxScale : 0;
597 if ( lst.count() < 6 )
617 *scaleFactor = 0.001;
618 return QStringLiteral(
"http://www.opengeospatial.org/se/units/metre" );
625 *scaleFactor = 1 / 0.28;
634 if ( str == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
637 *scaleFactor = 1000.0;
640 else if ( str == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
643 *scaleFactor = 304.8;
646 else if ( str == QLatin1String(
"http://www.opengeospatial.org/se/units/pixel" ) )
656 *scaleFactor = 1 / 0.00028;
662 QString vectorString;
663 QVector<qreal>::const_iterator it = v.constBegin();
664 for ( ; it != v.constEnd(); ++it )
666 if ( it != v.constBegin() )
668 vectorString.append(
';' );
670 vectorString.append( QString::number( *it ) );
677 QVector<qreal> resultVector;
679 QStringList realList = s.split(
';' );
680 QStringList::const_iterator it = realList.constBegin();
681 for ( ; it != realList.constEnd(); ++it )
683 resultVector.append( it->toDouble() );
691 QString vectorString;
692 QVector<qreal>::const_iterator it = v.constBegin();
693 for ( ; it != v.constEnd(); ++it )
695 if ( it != v.constBegin() )
697 vectorString.append(
' ' );
699 vectorString.append( QString::number( *it ) );
706 QVector<qreal> resultVector;
708 QStringList realList = s.split(
' ' );
709 QStringList::const_iterator it = realList.constBegin();
710 for ( ; it != realList.constEnd(); ++it )
712 resultVector.append( it->toDouble() );
720 QString encodedValue;
722 switch ( scaleMethod )
725 encodedValue = QStringLiteral(
"diameter" );
728 encodedValue = QStringLiteral(
"area" );
738 if ( str == QLatin1String(
"diameter" ) )
752 if ( s.compare( QLatin1String(
"Lighten" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Lighten;
753 if ( s.compare( QLatin1String(
"Screen" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Screen;
754 if ( s.compare( QLatin1String(
"Dodge" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorDodge;
755 if ( s.compare( QLatin1String(
"Addition" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Plus;
756 if ( s.compare( QLatin1String(
"Darken" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Darken;
757 if ( s.compare( QLatin1String(
"Multiply" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Multiply;
758 if ( s.compare( QLatin1String(
"Burn" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorBurn;
759 if ( s.compare( QLatin1String(
"Overlay" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Overlay;
760 if ( s.compare( QLatin1String(
"SoftLight" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_SoftLight;
761 if ( s.compare( QLatin1String(
"HardLight" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_HardLight;
762 if ( s.compare( QLatin1String(
"Difference" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Difference;
763 if ( s.compare( QLatin1String(
"Subtract" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Exclusion;
764 return QPainter::CompositionMode_SourceOver;
769 return QIcon(
symbolPreviewPixmap( symbol, size, padding,
nullptr,
false,
nullptr, shape ) );
775 QPixmap pixmap( size );
776 pixmap.fill( Qt::transparent );
778 painter.begin( &pixmap );
782 painter.setRenderHint( QPainter::Antialiasing );
791 size.setWidth( size.rwidth() - ( padding * 2 ) );
792 size.setHeight( size.rheight() - ( padding * 2 ) );
793 painter.translate( padding, padding );
803 std::unique_ptr<QgsSymbol> symbol_noDD( symbol->
clone( ) );
805 for (
const auto &layer : layers )
807 for (
int i = 0; i < layer->dataDefinedProperties().count(); ++i )
809 QgsProperty &prop = layer->dataDefinedProperties().property( i );
815 symbol_noDD->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape );
819 std::unique_ptr<QgsSymbol> symbolClone( symbol->
clone( ) );
820 symbolClone->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape );
834 maxBleed = layerMaxBleed > maxBleed ? layerMaxBleed : maxBleed;
844 painter.begin( &picture );
845 painter.setRenderHint( QPainter::Antialiasing );
849 QgsSymbolRenderContext symbolContext( renderContext, units, 1.0,
false, QgsSymbol::RenderHints(),
nullptr );
850 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
851 layerClone->drawPreviewIcon( symbolContext, size );
858 QPixmap pixmap( size );
859 pixmap.fill( Qt::transparent );
861 painter.begin( &pixmap );
862 painter.setRenderHint( QPainter::Antialiasing );
871 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
872 layerClone->drawPreviewIcon( symbolContext, size );
874 return QIcon( pixmap );
884 QPixmap pixmap( size );
885 pixmap.fill( Qt::transparent );
888 painter.begin( &pixmap );
891 if ( drawTransparentBackground )
892 drawStippledBackground( &painter, QRect( padding, padding, size.width() - padding * 2, size.height() - padding * 2 ) );
900 for (
int i = 0; i < size.width(); i++ )
902 QPen pen( ramp->
color(
static_cast< double >( i ) / size.width() ) );
903 painter.setPen( pen );
904 const int x = flipDirection ? size.width() - i - 1 : i;
905 painter.drawLine( x, 0 + padding, x, size.height() - 1 - padding );
912 for (
int i = 0; i < size.height(); i++ )
914 QPen pen( ramp->
color(
static_cast< double >( i ) / size.height() ) );
915 painter.setPen( pen );
916 const int y = flipDirection ? size.height() - i - 1 : i;
917 painter.drawLine( 0 + padding, y, size.width() - 1 - padding, y );
930 uchar pixDataRGB[] = { 255, 255, 255, 255,
935 QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
937 int width = ( rect.width() < rect.height() ) ?
938 rect.width() / 2.5 : rect.height() / 2.5;
939 QPixmap pix = QPixmap::fromImage( img.scaled( width, width ) );
942 brush.setTexture( pix );
943 painter->fillRect( rect, brush );
948 qreal s = ( markerSize - 1 ) / 2.0;
953 p.setPen( QColor( 50, 100, 120, 200 ) );
954 p.setBrush( QColor( 200, 200, 210, 120 ) );
955 p.drawEllipse( x - s, y - s, s * 2, s * 2 );
958 p.setPen( QColor( 255, 0, 0 ) );
959 p.drawLine( x - s, y + s, x + s, y - s );
960 p.drawLine( x - s, y - s, x + s, y + s );
972 static QPolygonF makeOffsetGeometry(
const QgsPolylineXY &polyline )
974 int i, pointCount = polyline.count();
976 QPolygonF resultLine;
977 resultLine.resize( pointCount );
981 for ( i = 0; i < pointCount; ++i, tempPtr++ )
982 resultLine[i] = QPointF( tempPtr->
x(), tempPtr->
y() );
986 static QList<QPolygonF> makeOffsetGeometry(
const QgsPolygonXY &polygon )
988 QList<QPolygonF> resultGeom;
989 resultGeom.reserve( polygon.size() );
990 for (
int ring = 0; ring < polygon.size(); ++ring )
991 resultGeom.append( makeOffsetGeometry( polygon[ ring ] ) );
997 QList<QPolygonF> resultLine;
999 if ( polyline.count() < 2 )
1001 resultLine.append( polyline );
1005 unsigned int i, pointCount = polyline.count();
1008 QPointF *tempPtr = polyline.data();
1009 for ( i = 0; i < pointCount; ++i, tempPtr++ )
1010 tempPolyline[i] =
QgsPointXY( tempPtr->rx(), tempPtr->ry() );
1013 if ( !tempGeometry.
isNull() )
1015 int quadSegments = 0;
1016 double miterLimit = 2.0;
1024 if ( !offsetGeom.
isNull() )
1026 tempGeometry = offsetGeom;
1031 resultLine.append( makeOffsetGeometry( line ) );
1036 resultLine.append( makeOffsetGeometry( tempGeometry.
asPolygon() ) );
1042 resultLine.reserve( tempMPolyline.count() );
1043 for (
int part = 0; part < tempMPolyline.count(); ++part )
1045 resultLine.append( makeOffsetGeometry( tempMPolyline[ part ] ) );
1052 resultLine.reserve( tempMPolygon.count() );
1053 for (
int part = 0; part < tempMPolygon.count(); ++part )
1055 resultLine.append( makeOffsetGeometry( tempMPolygon[ part ] ) );
1063 resultLine.append( polyline );
1073 QDomNode layerNode = element.firstChild();
1075 while ( !layerNode.isNull() )
1077 QDomElement e = layerNode.toElement();
1078 if ( !e.isNull() && e.tagName() != QLatin1String(
"data_defined_properties" ) )
1080 if ( e.tagName() != QLatin1String(
"layer" ) )
1091 QDomElement s = e.firstChildElement( QStringLiteral(
"symbol" ) );
1098 QgsDebugMsg(
"symbol layer refused subsymbol: " + s.attribute(
"name" ) );
1101 layers.append( layer );
1105 layerNode = layerNode.nextSibling();
1108 if ( layers.isEmpty() )
1110 QgsDebugMsg( QStringLiteral(
"no layers for symbol" ) );
1114 QString symbolType = element.attribute( QStringLiteral(
"type" ) );
1117 if ( symbolType == QLatin1String(
"line" ) )
1119 else if ( symbolType == QLatin1String(
"fill" ) )
1121 else if ( symbolType == QLatin1String(
"marker" ) )
1125 QgsDebugMsg(
"unknown symbol type " + symbolType );
1129 if ( element.hasAttribute( QStringLiteral(
"outputUnit" ) ) )
1133 if ( element.hasAttribute( ( QStringLiteral(
"mapUnitScale" ) ) ) )
1136 double oldMin = element.attribute( QStringLiteral(
"mapUnitMinScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1137 mapUnitScale.
minScale = oldMin != 0 ? 1.0 / oldMin : 0;
1138 double oldMax = element.attribute( QStringLiteral(
"mapUnitMaxScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1139 mapUnitScale.
maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
1142 symbol->
setOpacity( element.attribute( QStringLiteral(
"alpha" ), QStringLiteral(
"1.0" ) ).toDouble() );
1143 symbol->
setClipFeaturesToExtent( element.attribute( QStringLiteral(
"clip_to_extent" ), QStringLiteral(
"1" ) ).toInt() );
1144 symbol->
setForceRHR( element.attribute( QStringLiteral(
"force_rhr" ), QStringLiteral(
"0" ) ).toInt() );
1146 QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1147 if ( !ddProps.isNull() )
1157 QString layerClass = element.attribute( QStringLiteral(
"class" ) );
1158 bool locked = element.attribute( QStringLiteral(
"locked" ) ).toInt();
1159 bool enabled = element.attribute( QStringLiteral(
"enabled" ), QStringLiteral(
"1" ) ).toInt();
1160 int pass = element.attribute( QStringLiteral(
"pass" ) ).toInt();
1177 QDomElement effectElem = element.firstChildElement( QStringLiteral(
"effect" ) );
1178 if ( !effectElem.isNull() )
1186 QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1187 if ( !ddProps.isNull() )
1206 return QStringLiteral(
"line" );
1208 return QStringLiteral(
"marker" );
1210 return QStringLiteral(
"fill" );
1219 QDomElement symEl = doc.createElement( QStringLiteral(
"symbol" ) );
1220 symEl.setAttribute( QStringLiteral(
"type" ), _nameForSymbolType( symbol->
type() ) );
1221 symEl.setAttribute( QStringLiteral(
"name" ), name );
1222 symEl.setAttribute( QStringLiteral(
"alpha" ), QString::number( symbol->
opacity() ) );
1223 symEl.setAttribute( QStringLiteral(
"clip_to_extent" ), symbol->
clipFeaturesToExtent() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1224 symEl.setAttribute( QStringLiteral(
"force_rhr" ), symbol->
forceRHR() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1227 QDomElement ddProps = doc.createElement( QStringLiteral(
"data_defined_properties" ) );
1229 symEl.appendChild( ddProps );
1235 QDomElement layerEl = doc.createElement( QStringLiteral(
"layer" ) );
1236 layerEl.setAttribute( QStringLiteral(
"class" ), layer->
layerType() );
1237 layerEl.setAttribute( QStringLiteral(
"enabled" ), layer->
enabled() );
1238 layerEl.setAttribute( QStringLiteral(
"locked" ), layer->
isLocked() );
1239 layerEl.setAttribute( QStringLiteral(
"pass" ), layer->
renderingPass() );
1251 QDomElement ddProps = doc.createElement( QStringLiteral(
"data_defined_properties" ) );
1253 layerEl.appendChild( ddProps );
1257 QString subname = QStringLiteral(
"@%1@%2" ).arg( name ).arg( i );
1258 QDomElement subEl =
saveSymbol( subname, subSymbol, doc, context );
1259 layerEl.appendChild( subEl );
1261 symEl.appendChild( layerEl );
1269 QDomDocument doc( QStringLiteral(
"qgis-symbol-definition" ) );
1272 QTextStream stream( &props );
1273 symbolElem.save( stream, -1 );
1283 if ( element.isNull() )
1288 QString symbolizerName = element.localName();
1290 if ( symbolizerName == QLatin1String(
"PointSymbolizer" ) )
1293 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1294 if ( graphicElem.isNull() )
1296 QgsDebugMsg( QStringLiteral(
"Graphic element not found in PointSymbolizer" ) );
1332 if ( symbolizerName == QLatin1String(
"LineSymbolizer" ) )
1335 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1336 if ( strokeElem.isNull() )
1338 QgsDebugMsg( QStringLiteral(
"Stroke element not found in LineSymbolizer" ) );
1368 if ( symbolizerName == QLatin1String(
"PolygonSymbolizer" ) )
1371 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1372 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1373 if ( fillElem.isNull() && strokeElem.isNull() )
1375 QgsDebugMsg( QStringLiteral(
"neither Fill nor Stroke element not found in PolygonSymbolizer" ) );
1393 if ( l->
layerType() == QLatin1String(
"SimpleFill" ) || l->
layerType() == QLatin1String(
"SVGFill" ) )
1429 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1430 if ( fillElem.isNull() )
1432 QgsDebugMsg( QStringLiteral(
"Fill element not found" ) );
1452 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1453 if ( strokeElem.isNull() )
1455 QgsDebugMsg( QStringLiteral(
"Stroke element not found" ) );
1471 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1472 if ( graphicElem.isNull() )
1474 QgsDebugMsg( QStringLiteral(
"Graphic element not found" ) );
1494 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1495 if ( graphicElem.isNull() )
1498 QDomElement externalGraphicElem = graphicElem.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
1499 if ( externalGraphicElem.isNull() )
1503 QDomElement formatElem = externalGraphicElem.firstChildElement( QStringLiteral(
"Format" ) );
1504 if ( formatElem.isNull() )
1507 QString format = formatElem.firstChild().nodeValue();
1508 if ( format != QLatin1String(
"image/svg+xml" ) )
1510 QgsDebugMsg(
"unsupported External Graphic format found: " + format );
1515 QDomElement onlineResourceElem = externalGraphicElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1516 QDomElement inlineContentElem = externalGraphicElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1517 if ( !onlineResourceElem.isNull() )
1522 else if ( !inlineContentElem.isNull() )
1535 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1536 if ( graphicElem.isNull() )
1539 QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1540 if ( markElem.isNull() )
1543 QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
1544 return !wellKnownNameElem.isNull();
1550 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1551 if ( graphicElem.isNull() )
1554 QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1555 if ( markElem.isNull() )
1559 QDomElement formatElem = markElem.firstChildElement( QStringLiteral(
"Format" ) );
1560 if ( formatElem.isNull() )
1563 QString format = formatElem.firstChild().nodeValue();
1564 if ( format != QLatin1String(
"ttf" ) )
1566 QgsDebugMsg(
"unsupported Graphic Mark format found: " + format );
1571 QDomElement onlineResourceElem = markElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1572 QDomElement inlineContentElem = markElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1573 if ( !onlineResourceElem.isNull() )
1576 QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
1577 if ( !markIndexElem.isNull() )
1580 else if ( !inlineContentElem.isNull() )
1595 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1596 if ( graphicElem.isNull() )
1600 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
1602 if ( it.key() == QLatin1String(
"widthHeightFactor" ) )
1613 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1614 if ( strokeElem.isNull() )
1617 QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral(
"GraphicStroke" ) );
1618 if ( graphicStrokeElem.isNull() )
1626 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1627 if ( fillElem.isNull() )
1630 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1631 if ( graphicFillElem.isNull() )
1634 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1635 if ( graphicElem.isNull() )
1641 QColor fillColor, strokeColor;
1642 double size, strokeWidth;
1643 Qt::PenStyle strokeStyle;
1644 if ( !
wellKnownMarkerFromSld( graphicElem, name, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
1647 if ( name != QLatin1String(
"horline" ) )
1655 double angle = angleFunc.toDouble( &ok );
1667 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1668 if ( fillElem.isNull() )
1671 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1672 if ( graphicFillElem.isNull() )
1692 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1693 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1697 bool validFill =
false, validStroke =
false;
1702 Qt::BrushStyle fillStyle;
1704 if (
fillFromSld( fillElem, fillStyle, fillColor ) )
1710 Qt::PenStyle strokeStyle;
1711 double strokeWidth = 1.0, dashOffset = 0.0;
1712 QVector<qreal> customDashPattern;
1714 if (
lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth,
1715 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
1718 if ( validFill || validStroke )
1721 map[QStringLiteral(
"name" )] = QStringLiteral(
"square" );
1722 map[QStringLiteral(
"color" )] =
encodeColor( validFill ? fillColor : Qt::transparent );
1723 map[QStringLiteral(
"color_border" )] =
encodeColor( validStroke ? strokeColor : Qt::transparent );
1724 map[QStringLiteral(
"size" )] = QString::number( 6 );
1725 map[QStringLiteral(
"angle" )] = QString::number( 0 );
1726 map[QStringLiteral(
"offset" )] =
encodePoint( QPointF( 0, 0 ) );
1733 bool validFill =
false, validStroke =
false;
1736 QString name, format;
1738 QColor fillColor, strokeColor;
1739 double strokeWidth = 1.0, size = 0.0,
angle = 0.0;
1743 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1744 if ( !graphicFillElem.isNull() )
1747 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1748 if ( !graphicElem.isNull() )
1754 QDomElement graphicChildElem = graphicElem.firstChildElement();
1755 while ( !graphicChildElem.isNull() )
1757 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
1760 QDomElement wellKnownNameElem = graphicChildElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
1761 if ( !wellKnownNameElem.isNull() )
1763 name = wellKnownNameElem.firstChild().nodeValue();
1769 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) || graphicChildElem.localName() == QLatin1String(
"Mark" ) )
1772 QDomElement formatElem = graphicChildElem.firstChildElement( QStringLiteral(
"Format" ) );
1773 if ( formatElem.isNull() )
1776 format = formatElem.firstChild().nodeValue();
1780 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) && format != QLatin1String(
"image/svg+xml" ) )
1785 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format != QLatin1String(
"ttf" ) )
1789 QDomElement onlineResourceElem = graphicChildElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1790 QDomElement inlineContentElem = graphicChildElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1792 if ( !onlineResourceElem.isNull() )
1794 name = onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) );
1796 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format == QLatin1String(
"ttf" ) )
1799 if ( name.startsWith( QLatin1String(
"ttf://" ) ) )
1800 name = name.mid( 6 );
1803 QDomElement markIndexElem = graphicChildElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
1804 if ( markIndexElem.isNull() )
1808 int v = markIndexElem.firstChild().nodeValue().toInt( &ok );
1819 else if ( !inlineContentElem.isNull() )
1829 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
1831 name = QStringLiteral(
"square" );
1838 if ( found && graphicChildElem.localName() == QLatin1String(
"Mark" ) )
1845 Qt::BrushStyle markFillStyle;
1847 QDomElement markFillElem = graphicChildElem.firstChildElement( QStringLiteral(
"Fill" ) );
1848 if (
fillFromSld( markFillElem, markFillStyle, fillColor ) )
1853 Qt::PenStyle strokeStyle;
1854 double strokeWidth = 1.0, dashOffset = 0.0;
1855 QVector<qreal> customDashPattern;
1857 QDomElement markStrokeElem = graphicChildElem.firstChildElement( QStringLiteral(
"Stroke" ) );
1858 if (
lineFromSld( markStrokeElem, strokeStyle, strokeColor, strokeWidth,
1859 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
1866 QDomElement opacityElem = graphicElem.firstChildElement( QStringLiteral(
"Opacity" ) );
1867 if ( !opacityElem.isNull() )
1868 fillColor.setAlpha(
decodeSldAlpha( opacityElem.firstChild().nodeValue() ) );
1870 QDomElement sizeElem = graphicElem.firstChildElement( QStringLiteral(
"Size" ) );
1871 if ( !sizeElem.isNull() )
1874 double v = sizeElem.firstChild().nodeValue().toDouble( &ok );
1883 double v = angleFunc.toDouble( &ok );
1893 if ( validFill || validStroke )
1895 if ( format == QLatin1String(
"image/svg+xml" ) )
1898 map[QStringLiteral(
"name" )] = name;
1899 map[QStringLiteral(
"fill" )] = fillColor.name();
1900 map[QStringLiteral(
"outline" )] = strokeColor.name();
1901 map[QStringLiteral(
"outline-width" )] = QString::number( strokeWidth );
1903 map[QStringLiteral(
"size" )] = QString::number( size );
1905 map[QStringLiteral(
"angle" )] = QString::number(
angle );
1906 if ( !offset.isNull() )
1907 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
1910 else if ( format == QLatin1String(
"ttf" ) )
1913 map[QStringLiteral(
"font" )] = name;
1914 map[QStringLiteral(
"chr" )] = markIndex;
1915 map[QStringLiteral(
"color" )] =
encodeColor( validFill ? fillColor : Qt::transparent );
1917 map[QStringLiteral(
"size" )] = QString::number( size );
1919 map[QStringLiteral(
"angle" )] = QString::number(
angle );
1920 if ( !offset.isNull() )
1921 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
1927 if ( layers.isEmpty() )
1930 layerList << layers;
1937 QString patternName;
1938 switch ( brushStyle )
1943 case Qt::SolidPattern:
1944 if ( color.isValid() )
1947 if ( color.alpha() < 255 )
1952 case Qt::CrossPattern:
1953 case Qt::DiagCrossPattern:
1954 case Qt::HorPattern:
1955 case Qt::VerPattern:
1956 case Qt::BDiagPattern:
1957 case Qt::FDiagPattern:
1958 case Qt::Dense1Pattern:
1959 case Qt::Dense2Pattern:
1960 case Qt::Dense3Pattern:
1961 case Qt::Dense4Pattern:
1962 case Qt::Dense5Pattern:
1963 case Qt::Dense6Pattern:
1964 case Qt::Dense7Pattern:
1969 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( brushStyle ) ) );
1973 QDomElement graphicFillElem = doc.createElement( QStringLiteral(
"se:GraphicFill" ) );
1974 element.appendChild( graphicFillElem );
1976 QDomElement graphicElem = doc.createElement( QStringLiteral(
"se:Graphic" ) );
1977 graphicFillElem.appendChild( graphicElem );
1979 QColor fillColor = patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
1980 QColor strokeColor = !patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
1983 wellKnownMarkerToSld( doc, graphicElem, patternName, fillColor, strokeColor, Qt::SolidLine, -1, -1 );
1990 brushStyle = Qt::SolidPattern;
1991 color = QColor( 128, 128, 128 );
1993 if ( element.isNull() )
1995 brushStyle = Qt::NoBrush;
2000 QDomElement graphicFillElem = element.firstChildElement( QStringLiteral(
"GraphicFill" ) );
2002 if ( graphicFillElem.isNull() )
2005 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2007 QgsDebugMsg( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ) );
2009 if ( it.key() == QLatin1String(
"fill" ) )
2010 color = QColor( it.value() );
2011 else if ( it.key() == QLatin1String(
"fill-opacity" ) )
2017 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
2018 if ( graphicElem.isNull() )
2021 QString patternName = QStringLiteral(
"square" );
2022 QColor fillColor, strokeColor;
2023 double strokeWidth, size;
2024 Qt::PenStyle strokeStyle;
2025 if ( !
wellKnownMarkerFromSld( graphicElem, patternName, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
2029 if ( brushStyle == Qt::NoBrush )
2032 QColor
c = patternName.startsWith( QLatin1String(
"brush://" ) ) ? fillColor : strokeColor;
2041 Qt::PenStyle penStyle,
const QColor &color,
double width,
2042 const Qt::PenJoinStyle *penJoinStyle,
const Qt::PenCapStyle *penCapStyle,
2043 const QVector<qreal> *customDashPattern,
double dashOffset )
2045 QVector<qreal> dashPattern;
2046 const QVector<qreal> *pattern = &dashPattern;
2048 if ( penStyle == Qt::CustomDashLine && !customDashPattern )
2050 element.appendChild( doc.createComment( QStringLiteral(
"WARNING: Custom dash pattern required but not provided. Using default dash pattern." ) ) );
2051 penStyle = Qt::DashLine;
2063 dashPattern.push_back( 4.0 );
2064 dashPattern.push_back( 2.0 );
2067 dashPattern.push_back( 1.0 );
2068 dashPattern.push_back( 2.0 );
2070 case Qt::DashDotLine:
2071 dashPattern.push_back( 4.0 );
2072 dashPattern.push_back( 2.0 );
2073 dashPattern.push_back( 1.0 );
2074 dashPattern.push_back( 2.0 );
2076 case Qt::DashDotDotLine:
2077 dashPattern.push_back( 4.0 );
2078 dashPattern.push_back( 2.0 );
2079 dashPattern.push_back( 1.0 );
2080 dashPattern.push_back( 2.0 );
2081 dashPattern.push_back( 1.0 );
2082 dashPattern.push_back( 2.0 );
2085 case Qt::CustomDashLine:
2086 Q_ASSERT( customDashPattern );
2087 pattern = customDashPattern;
2091 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( penStyle ) ) );
2095 if ( color.isValid() )
2098 if ( color.alpha() < 255 )
2105 else if ( width == 0 )
2115 if ( !pattern->isEmpty() )
2125 Qt::PenStyle &penStyle, QColor &color,
double &width,
2126 Qt::PenJoinStyle *penJoinStyle, Qt::PenCapStyle *penCapStyle,
2127 QVector<qreal> *customDashPattern,
double *dashOffset )
2131 penStyle = Qt::SolidLine;
2132 color = QColor( 0, 0, 0 );
2135 *penJoinStyle = Qt::BevelJoin;
2137 *penCapStyle = Qt::SquareCap;
2138 if ( customDashPattern )
2139 customDashPattern->clear();
2143 if ( element.isNull() )
2145 penStyle = Qt::NoPen;
2151 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2153 QgsDebugMsg( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ) );
2155 if ( it.key() == QLatin1String(
"stroke" ) )
2157 color = QColor( it.value() );
2159 else if ( it.key() == QLatin1String(
"stroke-opacity" ) )
2163 else if ( it.key() == QLatin1String(
"stroke-width" ) )
2166 double w = it.value().toDouble( &ok );
2170 else if ( it.key() == QLatin1String(
"stroke-linejoin" ) && penJoinStyle )
2174 else if ( it.key() == QLatin1String(
"stroke-linecap" ) && penCapStyle )
2178 else if ( it.key() == QLatin1String(
"stroke-dasharray" ) )
2181 if ( !dashPattern.isEmpty() )
2185 bool dashPatternFound =
false;
2187 if ( dashPattern.count() == 2 )
2189 if ( dashPattern.at( 0 ) == 4.0 &&
2190 dashPattern.at( 1 ) == 2.0 )
2192 penStyle = Qt::DashLine;
2193 dashPatternFound =
true;
2195 else if ( dashPattern.at( 0 ) == 1.0 &&
2196 dashPattern.at( 1 ) == 2.0 )
2198 penStyle = Qt::DotLine;
2199 dashPatternFound =
true;
2202 else if ( dashPattern.count() == 4 )
2204 if ( dashPattern.at( 0 ) == 4.0 &&
2205 dashPattern.at( 1 ) == 2.0 &&
2206 dashPattern.at( 2 ) == 1.0 &&
2207 dashPattern.at( 3 ) == 2.0 )
2209 penStyle = Qt::DashDotLine;
2210 dashPatternFound =
true;
2213 else if ( dashPattern.count() == 6 )
2215 if ( dashPattern.at( 0 ) == 4.0 &&
2216 dashPattern.at( 1 ) == 2.0 &&
2217 dashPattern.at( 2 ) == 1.0 &&
2218 dashPattern.at( 3 ) == 2.0 &&
2219 dashPattern.at( 4 ) == 1.0 &&
2220 dashPattern.at( 5 ) == 2.0 )
2222 penStyle = Qt::DashDotDotLine;
2223 dashPatternFound =
true;
2228 if ( !dashPatternFound )
2230 if ( customDashPattern )
2232 penStyle = Qt::CustomDashLine;
2233 *customDashPattern = dashPattern;
2237 QgsDebugMsg( QStringLiteral(
"custom dash pattern required but not provided. Using default dash pattern." ) );
2238 penStyle = Qt::DashLine;
2243 else if ( it.key() == QLatin1String(
"stroke-dashoffset" ) && dashOffset )
2246 double d = it.value().toDouble( &ok );
2256 const QString &path,
const QString &mime,
2257 const QColor &color,
double size )
2259 QDomElement externalGraphicElem = doc.createElement( QStringLiteral(
"se:ExternalGraphic" ) );
2260 element.appendChild( externalGraphicElem );
2269 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2271 element.appendChild( sizeElem );
2276 const QString &path,
const QColor &fillColor,
double size,
const QColor &strokeColor,
double strokeWidth )
2283 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Parametric SVG" ) ) );
2287 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Plain SVG fallback, no parameters" ) ) );
2290 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Well known marker fallback" ) ) );
2296 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2298 graphicElem.appendChild( sizeElem );
2306 if ( fillColor.isValid() )
2308 url.addQueryItem( QStringLiteral(
"fill" ), fillColor.name() );
2309 url.addQueryItem( QStringLiteral(
"fill-opacity" ),
encodeSldAlpha( fillColor.alpha() ) );
2313 url.addQueryItem( QStringLiteral(
"fill" ), QStringLiteral(
"#000000" ) );
2314 url.addQueryItem( QStringLiteral(
"fill-opacity" ), QStringLiteral(
"1" ) );
2316 if ( strokeColor.isValid() )
2318 url.addQueryItem( QStringLiteral(
"outline" ), strokeColor.name() );
2319 url.addQueryItem( QStringLiteral(
"outline-opacity" ),
encodeSldAlpha( strokeColor.alpha() ) );
2323 url.addQueryItem( QStringLiteral(
"outline" ), QStringLiteral(
"#000000" ) );
2324 url.addQueryItem( QStringLiteral(
"outline-opacity" ), QStringLiteral(
"1" ) );
2326 url.addQueryItem( QStringLiteral(
"outline-width" ), QString::number( strokeWidth ) );
2327 QString params = url.toString( QUrl::FullyEncoded );
2328 if ( params.isEmpty() )
2334 return basePath +
"?" + params;
2339 QString &path, QString &mime,
2340 QColor &color,
double &size )
2345 QDomElement externalGraphicElem = element.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
2346 if ( externalGraphicElem.isNull() )
2351 QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2352 if ( !sizeElem.isNull() )
2355 double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2364 const QString &path,
const QString &format,
int *markIndex,
2365 const QColor &color,
double size )
2367 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2368 element.appendChild( markElem );
2374 QDomElement markIndexElem = doc.createElement( QStringLiteral(
"se:MarkIndex" ) );
2375 markIndexElem.appendChild( doc.createTextNode( QString::number( *markIndex ) ) );
2376 markElem.appendChild( markIndexElem );
2380 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2381 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2382 markElem.appendChild( fillElem );
2387 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2389 element.appendChild( sizeElem );
2394 QString &path, QString &format,
int &markIndex,
2395 QColor &color,
double &size )
2403 QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2404 if ( markElem.isNull() )
2409 QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
2410 if ( !markIndexElem.isNull() )
2413 int i = markIndexElem.firstChild().nodeValue().toInt( &ok );
2419 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2420 Qt::BrushStyle b = Qt::SolidPattern;
2425 QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2426 if ( !sizeElem.isNull() )
2429 double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2438 const QString &name,
const QColor &color,
const QColor &strokeColor, Qt::PenStyle strokeStyle,
2439 double strokeWidth,
double size )
2441 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2442 element.appendChild( markElem );
2444 QDomElement wellKnownNameElem = doc.createElement( QStringLiteral(
"se:WellKnownName" ) );
2445 wellKnownNameElem.appendChild( doc.createTextNode( name ) );
2446 markElem.appendChild( wellKnownNameElem );
2449 if ( color.isValid() )
2451 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2452 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2453 markElem.appendChild( fillElem );
2457 if ( strokeColor.isValid() )
2459 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
2460 lineToSld( doc, strokeElem, strokeStyle, strokeColor, strokeWidth );
2461 markElem.appendChild( strokeElem );
2467 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2469 element.appendChild( sizeElem );
2474 QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle,
2475 double &strokeWidth,
double &size )
2479 name = QStringLiteral(
"square" );
2481 strokeColor = QColor( 0, 0, 0 );
2485 QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2486 if ( markElem.isNull() )
2489 QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
2490 if ( !wellKnownNameElem.isNull() )
2492 name = wellKnownNameElem.firstChild().nodeValue();
2493 QgsDebugMsg(
"found Mark with well known name: " + name );
2497 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2498 Qt::BrushStyle b = Qt::SolidPattern;
2503 QDomElement strokeElem = markElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2504 lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth );
2508 QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2509 if ( !sizeElem.isNull() )
2512 double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2522 if ( !rotationFunc.isEmpty() )
2524 QDomElement rotationElem = doc.createElement( QStringLiteral(
"se:Rotation" ) );
2526 element.appendChild( rotationElem );
2532 QDomElement rotationElem = element.firstChildElement( QStringLiteral(
"Rotation" ) );
2533 if ( !rotationElem.isNull() )
2543 if ( !alphaFunc.isEmpty() )
2545 QDomElement opacityElem = doc.createElement( QStringLiteral(
"se:Opacity" ) );
2547 element.appendChild( opacityElem );
2553 QDomElement opacityElem = element.firstChildElement( QStringLiteral(
"Opacity" ) );
2554 if ( !opacityElem.isNull() )
2563 if ( offset.isNull() )
2566 QDomElement displacementElem = doc.createElement( QStringLiteral(
"se:Displacement" ) );
2567 element.appendChild( displacementElem );
2569 QDomElement dispXElem = doc.createElement( QStringLiteral(
"se:DisplacementX" ) );
2570 dispXElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.x(), 2 ) ) );
2572 QDomElement dispYElem = doc.createElement( QStringLiteral(
"se:DisplacementY" ) );
2573 dispYElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.y(), 2 ) ) );
2575 displacementElem.appendChild( dispXElem );
2576 displacementElem.appendChild( dispYElem );
2583 QDomElement anchorElem = doc.createElement( QStringLiteral(
"se:AnchorPoint" ) );
2584 element.appendChild( anchorElem );
2586 QDomElement anchorXElem = doc.createElement( QStringLiteral(
"se:AnchorPointX" ) );
2587 anchorXElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.x() ) ) );
2589 QDomElement anchorYElem = doc.createElement( QStringLiteral(
"se:AnchorPointY" ) );
2590 anchorYElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.y() ) ) );
2592 anchorElem.appendChild( anchorXElem );
2593 anchorElem.appendChild( anchorYElem );
2598 offset = QPointF( 0, 0 );
2600 QDomElement displacementElem = element.firstChildElement( QStringLiteral(
"Displacement" ) );
2601 if ( displacementElem.isNull() )
2604 QDomElement dispXElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementX" ) );
2605 if ( !dispXElem.isNull() )
2608 double offsetX = dispXElem.firstChild().nodeValue().toDouble( &ok );
2610 offset.setX( offsetX );
2613 QDomElement dispYElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementY" ) );
2614 if ( !dispYElem.isNull() )
2617 double offsetY = dispYElem.firstChild().nodeValue().toDouble( &ok );
2619 offset.setY( offsetY );
2626 const QString &label,
const QFont &font,
2627 const QColor &color,
double size )
2629 QDomElement labelElem = doc.createElement( QStringLiteral(
"se:Label" ) );
2630 labelElem.appendChild( doc.createTextNode( label ) );
2631 element.appendChild( labelElem );
2633 QDomElement fontElem = doc.createElement( QStringLiteral(
"se:Font" ) );
2634 element.appendChild( fontElem );
2638 fontElem.appendChild( createSldParameterElement( doc,
"font-style",
encodeSldFontStyle( font.style() ) ) );
2639 fontElem.appendChild( createSldParameterElement( doc,
"font-weight",
encodeSldFontWeight( font.weight() ) ) );
2644 if ( color.isValid() )
2646 QDomElement fillElem = doc.createElement( QStringLiteral(
"Fill" ) );
2647 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2648 element.appendChild( fillElem );
2653 Qt::PenJoinStyle joinStyle,
2654 Qt::PenCapStyle capStyle,
2656 const QVector<qreal> *dashPattern )
2659 penStyle.append(
"PEN(" );
2660 penStyle.append(
"c:" );
2661 penStyle.append(
c.name() );
2662 penStyle.append(
",w:" );
2664 penStyle.append( QString::number( width * mmScaleFactor ) );
2665 penStyle.append(
"mm" );
2668 if ( dashPattern && !dashPattern->isEmpty() )
2670 penStyle.append(
",p:\"" );
2671 QVector<qreal>::const_iterator pIt = dashPattern->constBegin();
2672 for ( ; pIt != dashPattern->constEnd(); ++pIt )
2674 if ( pIt != dashPattern->constBegin() )
2676 penStyle.append(
' ' );
2678 penStyle.append( QString::number( *pIt * mapUnitScaleFactor ) );
2679 penStyle.append(
'g' );
2681 penStyle.append(
'\"' );
2685 penStyle.append(
",cap:" );
2689 penStyle.append(
'p' );
2692 penStyle.append(
'r' );
2696 penStyle.append(
'b' );
2700 penStyle.append(
",j:" );
2701 switch ( joinStyle )
2704 penStyle.append(
'b' );
2707 penStyle.append(
'r' );
2711 penStyle.append(
'm' );
2717 penStyle.append(
",dp:" );
2718 penStyle.append( QString::number( offset * mapUnitScaleFactor ) );
2719 penStyle.append(
'g' );
2722 penStyle.append(
')' );
2729 brushStyle.append(
"BRUSH(" );
2730 brushStyle.append(
"fc:" );
2731 brushStyle.append( fillColor.name() );
2732 brushStyle.append(
')' );
2738 if ( geomFunc.isEmpty() )
2741 QDomElement geometryElem = doc.createElement( QStringLiteral(
"Geometry" ) );
2742 element.appendChild( geometryElem );
2772 QDomElement geometryElem = element.firstChildElement( QStringLiteral(
"Geometry" ) );
2773 if ( geometryElem.isNull() )
2785 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " +
function ) );
2789 if ( !filterElem.isNull() )
2790 element.appendChild( filterElem );
2801 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " +
function ) );
2805 if ( !filterElem.isNull() )
2806 element.appendChild( filterElem );
2813 QDomElement elem = element;
2814 if ( element.tagName() != QLatin1String(
"Filter" ) )
2816 QDomNodeList filterNodes = element.elementsByTagName( QStringLiteral(
"Filter" ) );
2817 if ( !filterNodes.isEmpty() )
2819 elem = filterNodes.at( 0 ).toElement();
2823 if ( elem.isNull() )
2848 const QString &path,
const QString &format )
2852 QDomElement onlineResourceElem = doc.createElement( QStringLiteral(
"se:OnlineResource" ) );
2853 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
2854 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:href" ), url );
2855 element.appendChild( onlineResourceElem );
2857 QDomElement formatElem = doc.createElement( QStringLiteral(
"se:Format" ) );
2858 formatElem.appendChild( doc.createTextNode( format ) );
2859 element.appendChild( formatElem );
2866 QDomElement onlineResourceElem = element.firstChildElement( QStringLiteral(
"OnlineResource" ) );
2867 if ( onlineResourceElem.isNull() )
2870 path = onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) );
2872 QDomElement formatElem = element.firstChildElement( QStringLiteral(
"Format" ) );
2873 if ( formatElem.isNull() )
2876 format = formatElem.firstChild().nodeValue();
2883 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:SvgParameter" ) );
2884 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
2885 nodeElem.appendChild( doc.createTextNode( value ) );
2894 QDomElement paramElem = element.firstChildElement();
2895 while ( !paramElem.isNull() )
2897 if ( paramElem.localName() == QLatin1String(
"SvgParameter" ) || paramElem.localName() == QLatin1String(
"CssParameter" ) )
2899 QString name = paramElem.attribute( QStringLiteral(
"name" ) );
2900 if ( paramElem.firstChild().nodeType() == QDomNode::TextNode )
2902 value = paramElem.firstChild().nodeValue();
2906 if ( paramElem.firstChild().nodeType() == QDomNode::ElementNode &&
2907 paramElem.firstChild().localName() == QLatin1String(
"Literal" ) )
2909 QgsDebugMsg( paramElem.firstChild().localName() );
2910 value = paramElem.firstChild().firstChild().nodeValue();
2914 QgsDebugMsg( QStringLiteral(
"unexpected child of %1" ).arg( paramElem.localName() ) );
2918 if ( !name.isEmpty() && !value.isEmpty() )
2919 params[ name ] = value;
2922 paramElem = paramElem.nextSiblingElement();
2930 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:VendorOption" ) );
2931 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
2932 nodeElem.appendChild( doc.createTextNode( value ) );
2940 QDomElement paramElem = element.firstChildElement( QStringLiteral(
"VendorOption" ) );
2941 while ( !paramElem.isNull() )
2943 QString name = paramElem.attribute( QStringLiteral(
"name" ) );
2944 QString value = paramElem.firstChild().nodeValue();
2946 if ( !name.isEmpty() && !value.isEmpty() )
2947 params[ name ] = value;
2949 paramElem = paramElem.nextSiblingElement( QStringLiteral(
"VendorOption" ) );
2959 if ( newSymbols.type() == QVariant::Map )
2961 return newSymbols.toMap();
2968 QDomElement e = element.firstChildElement();
2969 while ( !e.isNull() )
2971 if ( e.tagName() == QLatin1String(
"prop" ) )
2973 QString propKey = e.attribute( QStringLiteral(
"k" ) );
2974 QString propValue = e.attribute( QStringLiteral(
"v" ) );
2975 props[propKey] = propValue;
2977 e = e.nextSiblingElement();
2992 for ( QVariantMap::iterator it = props.begin(); it != props.end(); ++it )
2994 QDomElement propEl = doc.createElement( QStringLiteral(
"prop" ) );
2995 propEl.setAttribute( QStringLiteral(
"k" ), it.key() );
2996 propEl.setAttribute( QStringLiteral(
"v" ), it.value().toString() );
2997 element.appendChild( propEl );
3007 QDomElement e = element.firstChildElement();
3009 while ( !e.isNull() )
3011 if ( e.tagName() == QLatin1String(
"symbol" ) )
3015 symbols.insert( e.attribute( QStringLiteral(
"name" ) ), symbol );
3021 e = e.nextSiblingElement();
3028 QStringList subsymbols;
3030 for ( QMap<QString, QgsSymbol *>::iterator it = symbols.begin(); it != symbols.end(); ++it )
3032 if ( it.key()[0] !=
'@' )
3036 subsymbols.append( it.key() );
3038 QStringList parts = it.key().split(
'@' );
3039 if ( parts.count() < 3 )
3041 QgsDebugMsg(
"found subsymbol with invalid name: " + it.key() );
3045 QString symname = parts[1];
3046 int symlayer = parts[2].toInt();
3048 if ( !symbols.contains( symname ) )
3050 QgsDebugMsg(
"subsymbol references invalid symbol: " + symname );
3058 QgsDebugMsg(
"subsymbol references invalid symbol layer: " + QString::number( symlayer ) );
3067 QgsDebugMsg(
"symbol layer refused subsymbol: " + it.key() );
3074 for (
int i = 0; i < subsymbols.count(); i++ )
3075 symbols.take( subsymbols[i] );
3082 QDomElement symbolsElem = doc.createElement( tagName );
3085 for ( QMap<QString, QgsSymbol *>::iterator its = symbols.begin(); its != symbols.end(); ++its )
3087 QDomElement symEl =
saveSymbol( its.key(), its.value(), doc, context );
3088 symbolsElem.appendChild( symEl );
3096 qDeleteAll( symbols );
3105 std::unique_ptr< QMimeData >mimeData(
new QMimeData );
3107 QDomDocument symbolDoc;
3109 symbolDoc.appendChild( symbolElem );
3110 mimeData->setText( symbolDoc.toString() );
3113 mimeData->setColorData( symbol->
color() );
3115 return mimeData.release();
3123 QString text = data->text();
3124 if ( !text.isEmpty() )
3129 if ( doc.setContent( text ) )
3131 elem = doc.documentElement();
3133 if ( elem.nodeName() != QLatin1String(
"symbol" ) )
3134 elem = elem.firstChildElement( QStringLiteral(
"symbol" ) );
3145 QString rampType = element.attribute( QStringLiteral(
"type" ) );
3162 QgsDebugMsg(
"unknown colorramp type " + rampType );
3170 QDomElement rampEl = doc.createElement( QStringLiteral(
"colorramp" ) );
3171 rampEl.setAttribute( QStringLiteral(
"type" ), ramp->
type() );
3172 rampEl.setAttribute( QStringLiteral(
"name" ), name );
3180 QVariantMap rampMap;
3182 rampMap.insert( QStringLiteral(
"type" ), ramp->
type() );
3183 rampMap.insert( QStringLiteral(
"name" ), name );
3187 QVariantMap propertyMap;
3188 for (
auto property = properties.constBegin(); property != properties.constEnd(); ++property )
3190 propertyMap.insert( property.key(), property.value() );
3193 rampMap.insert( QStringLiteral(
"properties" ), propertyMap );
3199 QVariantMap rampMap = value.toMap();
3201 QString rampType = rampMap.
value( QStringLiteral(
"type" ) ).toString();
3204 QVariantMap propertyMap = rampMap.value( QStringLiteral(
"properties" ) ).toMap();
3207 for (
auto property = propertyMap.constBegin(); property != propertyMap.constEnd(); ++property )
3209 props.insert( property.key(), property.value().toString() );
3224 QgsDebugMsg(
"unknown colorramp type " + rampType );
3231 if ( !color.isValid() )
3238 return color.name();
3243 QList<QColor> colors;
3246 QStringList components = colorStr.simplified().split( QRegExp(
"(,|\\s)" ) );
3247 QStringList::iterator it = components.begin();
3248 for ( ; it != components.end(); ++it )
3251 if ( result.isValid() )
3256 if ( colors.length() > 0 )
3262 components = colorStr.split( QRegExp(
"(,|\n)" ) );
3263 it = components.begin();
3264 for ( ; it != components.end(); ++it )
3267 if ( result.isValid() )
3272 if ( colors.length() > 0 )
3278 components = colorStr.simplified().split( QString(
' ' ) );
3279 it = components.begin();
3280 for ( ; it != components.end(); ++it )
3283 if ( result.isValid() )
3288 if ( colors.length() > 0 )
3294 components = colorStr.split(
'\n' );
3295 it = components.begin();
3296 for ( ; it != components.end(); ++it )
3299 if ( result.isValid() )
3312 QMimeData *mimeData =
new QMimeData;
3313 mimeData->setColorData( QVariant( color ) );
3314 mimeData->setText( color.name() );
3321 if ( mimeData->hasColor() )
3323 QColor mimeColor = mimeData->colorData().value<QColor>();
3324 if ( mimeColor.isValid() )
3332 if ( mimeData->hasText() )
3336 if ( textColor.isValid() )
3351 if ( data->hasFormat( QStringLiteral(
"text/xml" ) ) )
3354 QByteArray encodedData = data->data( QStringLiteral(
"text/xml" ) );
3355 QDomDocument xmlDoc;
3356 xmlDoc.setContent( encodedData );
3358 QDomElement dragDataElem = xmlDoc.documentElement();
3359 if ( dragDataElem.tagName() == QLatin1String(
"ColorSchemeModelDragData" ) )
3361 QDomNodeList nodeList = dragDataElem.childNodes();
3362 int nChildNodes = nodeList.size();
3363 QDomElement currentElem;
3365 for (
int i = 0; i < nChildNodes; ++i )
3367 currentElem = nodeList.at( i ).toElement();
3368 if ( currentElem.isNull() )
3373 QPair< QColor, QString> namedColor;
3375 namedColor.second = currentElem.attribute( QStringLiteral(
"label" ), QString() );
3377 mimeColors << namedColor;
3382 if ( mimeColors.length() == 0 && data->hasFormat( QStringLiteral(
"application/x-colorobject-list" ) ) )
3385 QByteArray encodedData = data->data( QStringLiteral(
"application/x-colorobject-list" ) );
3386 QDomDocument xmlDoc;
3387 xmlDoc.setContent( encodedData );
3389 QDomNodeList colorsNodes = xmlDoc.elementsByTagName( QStringLiteral(
"colors" ) );
3390 if ( colorsNodes.length() > 0 )
3392 QDomElement colorsElem = colorsNodes.at( 0 ).toElement();
3393 QDomNodeList colorNodeList = colorsElem.childNodes();
3394 int nChildNodes = colorNodeList.size();
3395 QDomElement currentElem;
3397 for (
int i = 0; i < nChildNodes; ++i )
3400 currentElem = colorNodeList.at( i ).toElement();
3401 if ( currentElem.isNull() )
3406 QDomNodeList colorNodes = currentElem.elementsByTagName( QStringLiteral(
"color" ) );
3407 QDomNodeList nameNodes = currentElem.elementsByTagName( QStringLiteral(
"name" ) );
3409 if ( colorNodes.length() > 0 )
3411 QDomElement colorElem = colorNodes.at( 0 ).toElement();
3413 QStringList colorParts = colorElem.text().simplified().split(
' ' );
3414 if ( colorParts.length() < 3 )
3419 int red = colorParts.at( 0 ).toDouble() * 255;
3420 int green = colorParts.at( 1 ).toDouble() * 255;
3421 int blue = colorParts.at( 2 ).toDouble() * 255;
3422 QPair< QColor, QString> namedColor;
3423 namedColor.first = QColor( red, green, blue );
3424 if ( nameNodes.length() > 0 )
3426 QDomElement nameElem = nameNodes.at( 0 ).toElement();
3427 namedColor.second = nameElem.text();
3429 mimeColors << namedColor;
3435 if ( mimeColors.length() == 0 && data->hasText() )
3439 QList< QColor >::iterator it = parsedColors.begin();
3440 for ( ; it != parsedColors.end(); ++it )
3442 mimeColors << qMakePair( *it, QString() );
3446 if ( mimeColors.length() == 0 && data->hasColor() )
3449 QColor mimeColor = data->colorData().value<QColor>();
3450 if ( mimeColor.isValid() )
3452 mimeColors << qMakePair( mimeColor, QString() );
3462 QMimeData *mimeData =
new QMimeData();
3463 QDomDocument xmlDoc;
3464 QDomElement xmlRootElement = xmlDoc.createElement( QStringLiteral(
"ColorSchemeModelDragData" ) );
3465 xmlDoc.appendChild( xmlRootElement );
3467 QgsNamedColorList::const_iterator colorIt = colorList.constBegin();
3468 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3470 QDomElement namedColor = xmlDoc.createElement( QStringLiteral(
"NamedColor" ) );
3472 namedColor.setAttribute( QStringLiteral(
"label" ), ( *colorIt ).second );
3473 xmlRootElement.appendChild( namedColor );
3475 mimeData->setData( QStringLiteral(
"text/xml" ), xmlDoc.toByteArray() );
3483 colorIt = colorList.constBegin();
3484 QStringList colorListString;
3485 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3487 colorListString << ( *colorIt ).first.name();
3489 mimeData->setText( colorListString.join( QLatin1Char(
'\n' ) ) );
3492 if ( colorList.length() > 0 )
3494 mimeData->setColorData( QVariant( colorList.at( 0 ).first ) );
3502 if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3507 QTextStream stream( &file );
3508 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3509 stream <<
"GIMP Palette" << endl;
3511 stream <<
"GIMP Palette" << Qt::endl;
3513 if ( paletteName.isEmpty() )
3515 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3516 stream <<
"Name: QGIS Palette" << endl;
3518 stream <<
"Name: QGIS Palette" << Qt::endl;
3523 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3524 stream <<
"Name: " << paletteName << endl;
3526 stream <<
"Name: " << paletteName << Qt::endl;
3529 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3530 stream <<
"Columns: 4" << endl;
3531 stream <<
'#' << endl;
3533 stream <<
"Columns: 4" << Qt::endl;
3534 stream <<
'#' << Qt::endl;
3537 for ( QgsNamedColorList::ConstIterator colorIt = colors.constBegin(); colorIt != colors.constEnd(); ++colorIt )
3539 QColor color = ( *colorIt ).first;
3540 if ( !color.isValid() )
3544 stream << QStringLiteral(
"%1 %2 %3" ).arg( color.red(), 3 ).arg( color.green(), 3 ).arg( color.blue(), 3 );
3545 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3546 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << endl;
3548 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << Qt::endl;
3560 if ( !file.open( QIODevice::ReadOnly ) )
3563 return importedColors;
3566 QTextStream in( &file );
3568 QString line = in.readLine();
3569 if ( !line.startsWith( QLatin1String(
"GIMP Palette" ) ) )
3572 return importedColors;
3576 while ( !in.atEnd() && !line.startsWith( QLatin1String(
"Name:" ) ) && !line.startsWith(
'#' ) )
3578 line = in.readLine();
3580 if ( line.startsWith( QLatin1String(
"Name:" ) ) )
3582 QRegExp nameRx(
"Name:\\s*(\\S.*)$" );
3583 if ( nameRx.indexIn( line ) != -1 )
3585 name = nameRx.cap( 1 );
3590 while ( !in.atEnd() && !line.startsWith(
'#' ) )
3592 line = in.readLine();
3597 return importedColors;
3601 QRegExp rx(
"^\\s*(\\d+)\\s+(\\d+)\\s+(\\d+)(\\s.*)?$" );
3602 while ( !in.atEnd() )
3604 line = in.readLine();
3605 if ( rx.indexIn( line ) == -1 )
3609 int red = rx.cap( 1 ).toInt();
3610 int green = rx.cap( 2 ).toInt();
3611 int blue = rx.cap( 3 ).toInt();
3612 QColor color = QColor( red, green, blue );
3613 if ( !color.isValid() )
3620 if ( rx.captureCount() > 3 )
3622 label = rx.cap( 4 ).simplified();
3629 importedColors << qMakePair( color, label );
3634 return importedColors;
3647 QRegExp hexColorAlphaRx(
"^\\s*#?([0-9a-fA-F]{6})([0-9a-fA-F]{2})\\s*$" );
3648 int hexColorIndex = hexColorAlphaRx.indexIn( colorStr );
3651 if ( hexColorIndex == -1 && QColor::isValidColor( colorStr ) )
3654 parsedColor.setNamedColor( colorStr );
3655 if ( parsedColor.isValid() )
3657 containsAlpha =
false;
3663 if ( hexColorIndex > -1 )
3665 QString hexColor = hexColorAlphaRx.cap( 1 );
3666 parsedColor.setNamedColor( QStringLiteral(
"#" ) + hexColor );
3668 int alphaHex = hexColorAlphaRx.cap( 2 ).toInt( &alphaOk, 16 );
3670 if ( parsedColor.isValid() && alphaOk )
3672 parsedColor.setAlpha( alphaHex );
3673 containsAlpha =
true;
3681 QRegExp hexColorRx2(
"^\\s*(?:[0-9a-fA-F]{3}){1,2}\\s*$" );
3682 if ( hexColorRx2.indexIn( colorStr ) != -1 )
3685 parsedColor.setNamedColor( QStringLiteral(
"#" ) + colorStr );
3686 if ( parsedColor.isValid() )
3688 containsAlpha =
false;
3695 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*$" );
3696 if ( rgbFormatRx.indexIn( colorStr ) != -1 )
3698 int r = rgbFormatRx.cap( 1 ).toInt();
3699 int g = rgbFormatRx.cap( 2 ).toInt();
3700 int b = rgbFormatRx.cap( 3 ).toInt();
3701 parsedColor.setRgb( r, g, b );
3702 if ( parsedColor.isValid() )
3704 containsAlpha =
false;
3710 const QRegularExpression hslFormatRx(
"^\\s*hsl\\(?\\s*(\\d+)\\s*,\\s*(\\d+)\\s*%\\s*,\\s*(\\d+)\\s*%\\s*\\)?\\s*;?\\s*$" );
3711 QRegularExpressionMatch match = hslFormatRx.match( colorStr );
3712 if ( match.hasMatch() )
3714 int h = match.captured( 1 ).toInt();
3715 int s = match.captured( 2 ).toInt();
3716 int l = match.captured( 3 ).toInt();
3717 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0 );
3718 if ( parsedColor.isValid() )
3720 containsAlpha =
false;
3726 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*$" );
3727 if ( rgbPercentFormatRx.indexIn( colorStr ) != -1 )
3729 int r = std::round( rgbPercentFormatRx.cap( 1 ).toDouble() * 2.55 );
3730 int g = std::round( rgbPercentFormatRx.cap( 2 ).toDouble() * 2.55 );
3731 int b = std::round( rgbPercentFormatRx.cap( 3 ).toDouble() * 2.55 );
3732 parsedColor.setRgb( r, g, b );
3733 if ( parsedColor.isValid() )
3735 containsAlpha =
false;
3741 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*$" );
3742 if ( rgbaFormatRx.indexIn( colorStr ) != -1 )
3744 int r = rgbaFormatRx.cap( 1 ).toInt();
3745 int g = rgbaFormatRx.cap( 2 ).toInt();
3746 int b = rgbaFormatRx.cap( 3 ).toInt();
3747 int a = std::round( rgbaFormatRx.cap( 4 ).toDouble() * 255.0 );
3748 parsedColor.setRgb( r, g, b, a );
3749 if ( parsedColor.isValid() )
3751 containsAlpha =
true;
3757 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*$" );
3758 if ( rgbaPercentFormatRx.indexIn( colorStr ) != -1 )
3760 int r = std::round( rgbaPercentFormatRx.cap( 1 ).toDouble() * 2.55 );
3761 int g = std::round( rgbaPercentFormatRx.cap( 2 ).toDouble() * 2.55 );
3762 int b = std::round( rgbaPercentFormatRx.cap( 3 ).toDouble() * 2.55 );
3763 int a = std::round( rgbaPercentFormatRx.cap( 4 ).toDouble() * 255.0 );
3764 parsedColor.setRgb( r, g, b, a );
3765 if ( parsedColor.isValid() )
3767 containsAlpha =
true;
3773 const QRegularExpression hslaPercentFormatRx(
"^\\s*hsla\\(?\\s*(\\d+)\\s*,\\s*(\\d+)\\s*%\\s*,\\s*(\\d+)\\s*%\\s*,\\s*([\\d\\.]+)\\s*\\)?\\s*;?\\s*$" );
3774 match = hslaPercentFormatRx.match( colorStr );
3775 if ( match.hasMatch() )
3777 int h = match.captured( 1 ).toInt();
3778 int s = match.captured( 2 ).toInt();
3779 int l = match.captured( 3 ).toInt();
3780 int a = std::round( match.captured( 4 ).toDouble() * 255.0 );
3781 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0, a );
3782 if ( parsedColor.isValid() )
3784 containsAlpha =
true;
3801 QImage::Format format = image->format();
3802 if ( format != QImage::Format_ARGB32_Premultiplied && format != QImage::Format_ARGB32 )
3804 QgsDebugMsg( QStringLiteral(
"no alpha channel." ) );
3809 for (
int heightIndex = 0; heightIndex < image->height(); ++heightIndex )
3811 QRgb *scanLine =
reinterpret_cast< QRgb *
>( image->scanLine( heightIndex ) );
3812 for (
int widthIndex = 0; widthIndex < image->width(); ++widthIndex )
3814 myRgb = scanLine[widthIndex];
3815 if ( format == QImage::Format_ARGB32_Premultiplied )
3816 scanLine[widthIndex] = qRgba( opacity * qRed( myRgb ), opacity * qGreen( myRgb ), opacity * qBlue( myRgb ), opacity * qAlpha( myRgb ) );
3818 scanLine[widthIndex] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), opacity * qAlpha( myRgb ) );
3826 int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
3827 int alpha = ( radius < 1 ) ? 16 : ( radius > 17 ) ? 1 : tab[radius - 1];
3829 if ( image.format() != QImage::Format_ARGB32_Premultiplied
3830 && image.format() != QImage::Format_RGB32 )
3832 image = image.convertToFormat( QImage::Format_ARGB32_Premultiplied );
3835 int r1 = rect.top();
3836 int r2 = rect.bottom();
3837 int c1 = rect.left();
3838 int c2 = rect.right();
3840 int bpl = image.bytesPerLine();
3848 i1 = i2 = ( QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3 );
3850 for (
int col = c1; col <= c2; col++ )
3852 p = image.scanLine( r1 ) + col * 4;
3853 for (
int i = i1; i <= i2; i++ )
3854 rgba[i] = p[i] << 4;
3857 for (
int j = r1; j < r2; j++, p += bpl )
3858 for (
int i = i1; i <= i2; i++ )
3859 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
3862 for (
int row = r1; row <= r2; row++ )
3864 p = image.scanLine( row ) + c1 * 4;
3865 for (
int i = i1; i <= i2; i++ )
3866 rgba[i] = p[i] << 4;
3869 for (
int j = c1; j < c2; j++, p += 4 )
3870 for (
int i = i1; i <= i2; i++ )
3871 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
3874 for (
int col = c1; col <= c2; col++ )
3876 p = image.scanLine( r2 ) + col * 4;
3877 for (
int i = i1; i <= i2; i++ )
3878 rgba[i] = p[i] << 4;
3881 for (
int j = r1; j < r2; j++, p -= bpl )
3882 for (
int i = i1; i <= i2; i++ )
3883 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
3886 for (
int row = r1; row <= r2; row++ )
3888 p = image.scanLine( row ) + c2 * 4;
3889 for (
int i = i1; i <= i2; i++ )
3890 rgba[i] = p[i] << 4;
3893 for (
int j = c1; j < c2; j++, p -= 4 )
3894 for (
int i = i1; i <= i2; i++ )
3895 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
3901 if ( alpha != 255 && alpha > 0 )
3905 double alphaFactor = alpha / 255.;
3906 int r = 0, g = 0, b = 0;
3907 rgb.getRgb( &r, &g, &b );
3912 rgb.setRgb( r, g, b, alpha );
3914 else if ( alpha == 0 )
3916 rgb.setRgb( 0, 0, 0, 0 );
3922 if ( order == Qt::AscendingOrder )
3936 double dx = directionPoint.x() - startPoint.x();
3937 double dy = directionPoint.y() - startPoint.y();
3938 double length = std::sqrt( dx * dx + dy * dy );
3939 double scaleFactor = distance / length;
3940 return QPointF( startPoint.x() + dx * scaleFactor, startPoint.y() + dy * scaleFactor );
3950 for (
int i = 0; i < svgPaths.size(); i++ )
3952 QDir dir( svgPaths[i] );
3953 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
3954 for (
const QString &item : svgSubPaths )
3956 svgPaths.insert( i + 1, dir.path() +
'/' + item );
3959 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
3960 for (
const QString &item : svgFiles )
3963 list.append( dir.path() +
'/' + item );
3975 QStringList svgPaths;
3976 svgPaths.append( directory );
3978 for (
int i = 0; i < svgPaths.size(); i++ )
3980 QDir dir( svgPaths[i] );
3981 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
3982 for (
const QString &item : svgSubPaths )
3984 svgPaths.insert( i + 1, dir.path() +
'/' + item );
3987 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
3988 for (
const QString &item : svgFiles )
3990 list.append( dir.path() +
'/' + item );
4002 if ( n.startsWith( QLatin1String(
"base64:" ) ) )
4006 if ( QFileInfo::exists( n ) )
4007 return QFileInfo( n ).canonicalFilePath();
4011 if ( name.contains( QLatin1String(
"://" ) ) )
4014 if ( url.isValid() && !url.scheme().isEmpty() )
4016 if ( url.scheme().compare( QLatin1String(
"file" ), Qt::CaseInsensitive ) == 0 )
4019 name = url.toLocalFile();
4020 if ( QFile( name ).exists() )
4022 return QFileInfo( name ).canonicalFilePath();
4036 for (
int i = 0; i < svgPaths.size(); i++ )
4038 QString svgPath = svgPaths[i];
4039 if ( svgPath.endsWith( QChar(
'/' ) ) )
4050 QString myLocalPath = svgPath + QDir::separator() + name;
4053 if ( QFile( myLocalPath ).exists() )
4056 return QFileInfo( myLocalPath ).canonicalFilePath();
4060 return pathResolver.
readPath( name );
4068 if ( p.startsWith( QLatin1String(
"base64:" ) ) )
4071 if ( !QFileInfo::exists( p ) )
4074 QString path = QFileInfo( p ).canonicalFilePath();
4078 bool isInSvgPaths =
false;
4079 for (
int i = 0; i < svgPaths.size(); i++ )
4081 QString dir = QFileInfo( svgPaths[i] ).canonicalFilePath();
4083 if ( !dir.isEmpty() && path.startsWith( dir ) )
4085 path = path.mid( dir.size() + 1 );
4086 isInSvgPaths =
true;
4101 double cx = 0, cy = 0;
4102 double area, sum = 0;
4103 for (
int i = points.count() - 1, j = 0; j < points.count(); i = j++ )
4105 const QPointF &p1 = points[i];
4106 const QPointF &p2 = points[j];
4107 area = p1.x() * p2.y() - p1.y() * p2.x();
4109 cx += ( p1.x() + p2.x() ) * area;
4110 cy += ( p1.y() + p2.y() ) * area;
4117 if ( points.count() >= 2 )
4118 return QPointF( ( points[0].x() + points[1].x() ) / 2, ( points[0].y() + points[1].y() ) / 2 );
4119 else if ( points.count() == 1 )
4127 return QPointF( cx, cy );
4134 if ( ( rings && rings->count() > 0 ) || !
pointInPolygon( points, centroid ) )
4136 unsigned int i, pointCount = points.count();
4138 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( points[i].x(), points[i].y() );
4144 for (
auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
4146 pointCount = ( *ringIt ).count();
4148 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( ( *ringIt )[i].x(), ( *ringIt )[i].y() );
4154 if ( !pointOnSurfaceGeom.
isNull() )
4157 centroid.
setX( point.
x() );
4158 centroid.setY( point.
y() );
4163 return QPointF( centroid.x(), centroid.y() );
4168 bool inside =
false;
4170 double x = point.x();
4171 double y = point.y();
4173 for (
int i = 0, j = points.count() - 1; i < points.count(); i++ )
4175 const QPointF &p1 = points[i];
4176 const QPointF &p2 = points[j];
4181 if ( ( p1.y() < y && p2.y() >= y ) || ( p2.y() < y && p1.y() >= y ) )
4183 if ( p1.x() + ( y - p1.y() ) / ( p2.y() - p1.y() ) * ( p2.x() - p1.x() ) <= x )
4194 if ( polyline.size() < 2 )
4197 double totalLength = 0;
4198 auto it = polyline.begin();
4200 std::vector< double > segmentLengths( polyline.size() - 1 );
4201 auto segmentLengthIt = segmentLengths.begin();
4202 for ( ; it != polyline.end(); ++it )
4205 *segmentLengthIt = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4206 totalLength += *segmentLengthIt;
4212 if ( startOffset >= 0 && totalLength <= startOffset )
4214 if ( endOffset < 0 && totalLength <= -endOffset )
4217 const double startDistance = startOffset < 0 ? totalLength + startOffset : startOffset;
4218 const double endDistance = endOffset <= 0 ? totalLength + endOffset : endOffset;
4219 QPolygonF substringPoints;
4220 substringPoints.reserve( polyline.size() );
4222 it = polyline.begin();
4223 segmentLengthIt = segmentLengths.begin();
4226 bool foundStart =
false;
4227 if (
qgsDoubleNear( startDistance, 0.0 ) || startDistance < 0 )
4229 substringPoints << p1;
4233 double distanceTraversed = 0;
4234 for ( ; it != polyline.end(); ++it )
4237 if ( distanceTraversed < startDistance && distanceTraversed + *segmentLengthIt > startDistance )
4240 const double distanceToStart = startDistance - distanceTraversed;
4241 double startX, startY;
4243 substringPoints << QPointF( startX, startY );
4246 if ( foundStart && ( distanceTraversed + *segmentLengthIt > endDistance ) )
4249 const double distanceToEnd = endDistance - distanceTraversed;
4252 if ( substringPoints.last() != QPointF( endX, endY ) )
4253 substringPoints << QPointF( endX, endY );
4255 else if ( foundStart )
4257 if ( substringPoints.last() != QPointF( p2.x(), p2.y() ) )
4258 substringPoints << QPointF( p2.x(), p2.y() );
4261 distanceTraversed += *segmentLengthIt;
4262 if ( distanceTraversed > endDistance )
4269 if ( ( substringPoints.size() < 2 ) || ( substringPoints.size() == 2 && substringPoints.at( 0 ) == substringPoints.at( 1 ) ) )
4272 return substringPoints;
4277 double vertexAngle = M_PI - ( std::atan2( p3.y() - p2.y(), p3.x() - p2.x() ) - std::atan2( p2.y() - p1.y(), p2.x() - p1.x() ) );
4281 return vertexAngle < M_PI * 135.0 / 180.0 || vertexAngle > M_PI * 225.0 / 180.0;
4286 target.reserve( target.size() + line.size() );
4287 for (
const QPointF &pt : line )
4289 if ( !target.empty() && target.last() == pt )
4298 if ( fieldOrExpression.isEmpty() )
4333 QList<double> breaks;
4336 breaks.append( maximum );
4340 int minimumCount =
static_cast< int >( classes ) / 3;
4341 double shrink = 0.75;
4342 double highBias = 1.5;
4343 double adjustBias = 0.5 + 1.5 * highBias;
4344 int divisions = classes;
4345 double h = highBias;
4348 double dx = maximum - minimum;
4358 cell = std::max( std::fabs( minimum ), std::fabs( maximum ) );
4359 if ( adjustBias >= 1.5 * h + 0.5 )
4361 U = 1 + ( 1.0 / ( 1 + h ) );
4365 U = 1 + ( 1.5 / ( 1 + adjustBias ) );
4367 small = dx < ( cell * U * std::max( 1, divisions ) * 1e-07 * 3.0 );
4374 cell = 9 + cell / 10;
4375 cell = cell * shrink;
4377 if ( minimumCount > 1 )
4379 cell = cell / minimumCount;
4385 if ( divisions > 1 )
4387 cell = cell / divisions;
4390 if ( cell < 20 * 1e-07 )
4395 double base = std::pow( 10.0, std::floor( std::log10( cell ) ) );
4397 if ( ( 2 * base ) - cell < h * ( cell - unit ) )
4400 if ( ( 5 * base ) - cell < adjustBias * ( cell - unit ) )
4403 if ( ( 10.0 * base ) - cell < h * ( cell - unit ) )
4410 int start = std::floor( minimum / unit + 1e-07 );
4411 int end = std::ceil( maximum / unit - 1e-07 );
4414 while ( start * unit > minimum + ( 1e-07 * unit ) )
4418 while ( end * unit < maximum - ( 1e-07 * unit ) )
4422 QgsDebugMsg( QStringLiteral(
"pretty classes: %1" ).arg( end ) );
4426 int k = std::floor( 0.5 + end - start );
4427 if ( k < minimumCount )
4429 k = minimumCount - k;
4433 start = start - k / 2 + k % 2;
4437 start = start - k / 2;
4438 end = end + k / 2 + k % 2;
4441 double minimumBreak = start * unit;
4443 int count = end - start;
4445 breaks.reserve( count );
4446 for (
int i = 1; i < count + 1; i++ )
4448 breaks.append( minimumBreak + i * unit );
4451 if ( breaks.isEmpty() )
4454 if ( breaks.first() < minimum )
4456 breaks[0] = minimum;
4458 if ( breaks.last() > maximum )
4460 breaks[breaks.count() - 1] = maximum;
4465 if ( minimum < 0.0 && maximum > 0.0 )
4467 QList<double> breaksMinusZero;
4468 for (
int i = 0; i < breaks.count(); i++ )
4470 breaksMinusZero.append( breaks[i] - 0.0 );
4473 for (
int i = 1; i < breaks.count(); i++ )
4475 if ( std::abs( breaksMinusZero[i] ) < std::abs( breaksMinusZero[i - 1] ) )
4478 breaks[posOfMin] = 0.0;
4487 bool roundToUnit =
false;
4490 if ( props.contains( QStringLiteral(
"uomScale" ) ) )
4493 scale = props.value( QStringLiteral(
"uomScale" ) ).toDouble( &ok );
4502 if ( props.value( QStringLiteral(
"uom" ) ) == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
4527 scale = 1 / 0.28 * 25.4;
4551 double rescaled = size * scale;
4556 rescaled = std::round( rescaled );
4563 double x =
rescaleUom( point.x(), unit, props );
4564 double y =
rescaleUom( point.y(), unit, props );
4565 return QPointF( x, y );
4570 QVector<qreal> result;
4571 QVector<qreal>::const_iterator it = array.constBegin();
4572 for ( ; it != array.constEnd(); ++it )
4574 result.append(
rescaleUom( *it, unit, props ) );
4581 if ( !props.value( QStringLiteral(
"scaleMinDenom" ), QString() ).toString().isEmpty() )
4583 QDomElement scaleMinDenomElem = doc.createElement( QStringLiteral(
"se:MinScaleDenominator" ) );
4584 scaleMinDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMinDenom" ) ).toString().toDouble() ) ) );
4585 ruleElem.appendChild( scaleMinDenomElem );
4588 if ( !props.value( QStringLiteral(
"scaleMaxDenom" ), QString() ).toString().isEmpty() )
4590 QDomElement scaleMaxDenomElem = doc.createElement( QStringLiteral(
"se:MaxScaleDenominator" ) );
4591 scaleMaxDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMaxDenom" ) ).toString().toDouble() ) ) );
4592 ruleElem.appendChild( scaleMaxDenomElem );
4601 double parentScaleMinDenom = props.value( QStringLiteral(
"scaleMinDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
4602 if ( !ok || parentScaleMinDenom <= 0 )
4603 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( mScaleMinDenom );
4605 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( std::max( parentScaleMinDenom, mScaleMinDenom ) );
4611 double parentScaleMaxDenom = props.value( QStringLiteral(
"scaleMaxDenom" ), QStringLiteral(
"0" ) ).toString().toDouble( &ok );
4612 if ( !ok || parentScaleMaxDenom <= 0 )
4613 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( mScaleMaxDenom );
4615 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( std::min( parentScaleMaxDenom, mScaleMaxDenom ) );
4623 if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
4625 scale = 1.0 / 0.00028;
4627 else if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
4629 scale = 304.8 / 0.28;
4636 return size * scale;
4644 SymbolLayerVisitor(
const QSet<QgsSymbolLayerId> &layerIds )
4645 : mSymbolLayerIds( layerIds )
4658 void visitSymbol(
const QgsSymbol *symbol,
const QString &identifier, QVector<int> rootPath )
4662 QVector<int> indexPath = rootPath;
4663 indexPath.append( idx );
4665 if ( mSymbolLayerIds.contains(
QgsSymbolLayerId( mCurrentRuleKey + identifier, indexPath ) ) )
4667 mSymbolLayers.insert( sl );
4672 visitSymbol( subSymbol, identifier, indexPath );
4681 if ( symbolEntity->symbol() )
4683 visitSymbol( symbolEntity->symbol(), leaf.
identifier, {} );
4689 QString mCurrentRuleKey;
4690 const QSet<QgsSymbolLayerId> &mSymbolLayerIds;
4691 QSet<const QgsSymbolLayer *> mSymbolLayers;
4694 SymbolLayerVisitor visitor( symbolLayerIds );
4695 renderer->
accept( &visitor );
4696 return visitor.mSymbolLayers;
4701 if ( !s || !context )
4711 size = markerSymbol->
size( *context );
4713 else if ( lineSymbol )
4715 size = lineSymbol->
width( *context );
4724 if ( minSize > 0 && size < minSize )
4728 else if ( maxSize > 0 && size > maxSize )
4746 else if ( lineSymbol )
4760 QMap<QString, QgsProperty>::const_iterator paramIt = propertiesMap.constBegin();
4761 for ( ; paramIt != propertiesMap.constEnd(); ++paramIt )
4763 properties.insert( paramIt.key(), paramIt.value().valueAsString( context ) );
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...
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.
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.
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 bool createSymbolLayerListFromSld(QDomElement &element, QgsWkbTypes::GeometryType geomType, QgsSymbolLayerList &layers)
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 convertPolygonSymbolizerToPointMarker(QDomElement &element, QgsSymbolLayerList &layerList)
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 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 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 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 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 QgsSymbol::ScaleMethod decodeScaleMethod(const QString &str)
static double estimateMaxSymbolBleed(QgsSymbol *symbol, const QgsRenderContext &context)
Returns the maximum estimated bleed for the symbol.
static void wellKnownMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &name, const QColor &color, const QColor &strokeColor, Qt::PenStyle strokeStyle, double strokeWidth=-1, double size=-1)
static QString symbolProperties(QgsSymbol *symbol)
Returns a string representing the symbol.
static bool geometryFromSldElement(QDomElement &element, QString &geomFunc)
static 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 encodeScaleMethod(QgsSymbol::ScaleMethod scaleMethod)
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
static QgsStringMap getVendorOptionList(QDomElement &element)
static QMimeData * colorToMimeData(const QColor &color)
Creates mime data from a color.
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)
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)
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
virtual bool setSubSymbol(QgsSymbol *symbol)
Sets layer's subsymbol. takes ownership of the passed symbol.
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.
@ ScaleArea
Calculate scale by the area.
@ ScaleDiameter
Calculate scale by the diameter.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol property definitions.
SymbolType type() const
Returns the symbol's type.
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.
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.
SymbolType
Type of the symbol.
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.
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.