41 #include <QDomDocument>
43 #include <QDomElement>
50 #define POINTS_TO_MM 2.83464567
54 return QStringLiteral(
"%1,%2,%3,%4" ).arg( color.red() ).arg( color.green() ).arg( color.blue() ).arg( color.alpha() );
59 const QStringList lst = str.split(
',' );
60 if ( lst.count() < 3 )
64 int red, green, blue, alpha;
66 green = lst[1].toInt();
67 blue = lst[2].toInt();
69 if ( lst.count() > 3 )
71 alpha = lst[3].toInt();
73 return QColor( red, green, blue, alpha );
78 return QString::number( alpha / 255.0,
'g', 2 );
84 double alpha = str.toDouble( &ok );
85 if ( !ok || alpha > 1 )
96 case QFont::StyleNormal:
97 return QStringLiteral(
"normal" );
98 case QFont::StyleItalic:
99 return QStringLiteral(
"italic" );
100 case QFont::StyleOblique:
101 return QStringLiteral(
"oblique" );
109 if ( str == QLatin1String(
"normal" ) )
return QFont::StyleNormal;
110 if ( str == QLatin1String(
"italic" ) )
return QFont::StyleItalic;
111 if ( str == QLatin1String(
"oblique" ) )
return QFont::StyleOblique;
112 return QFont::StyleNormal;
117 if ( weight == 50 )
return QStringLiteral(
"normal" );
118 if ( weight == 75 )
return QStringLiteral(
"bold" );
122 if ( weight < 0 )
return QStringLiteral(
"100" );
123 if ( weight > 99 )
return QStringLiteral(
"900" );
124 return QString::number( weight * 800 / 99 + 100 );
130 int weight = str.toInt( &ok );
132 return static_cast< int >( QFont::Normal );
136 if ( weight > 900 )
return 99;
137 if ( weight < 100 )
return 0;
138 return ( weight - 100 ) * 99 / 800;
146 return QStringLiteral(
"no" );
148 return QStringLiteral(
"solid" );
150 return QStringLiteral(
"dash" );
152 return QStringLiteral(
"dot" );
153 case Qt::DashDotLine:
154 return QStringLiteral(
"dash dot" );
155 case Qt::DashDotDotLine:
156 return QStringLiteral(
"dash dot dot" );
158 return QStringLiteral(
"???" );
164 if ( str == QLatin1String(
"no" ) )
return Qt::NoPen;
165 if ( str == QLatin1String(
"solid" ) )
return Qt::SolidLine;
166 if ( str == QLatin1String(
"dash" ) )
return Qt::DashLine;
167 if ( str == QLatin1String(
"dot" ) )
return Qt::DotLine;
168 if ( str == QLatin1String(
"dash dot" ) )
return Qt::DashDotLine;
169 if ( str == QLatin1String(
"dash dot dot" ) )
return Qt::DashDotDotLine;
170 return Qt::SolidLine;
178 return QStringLiteral(
"bevel" );
180 return QStringLiteral(
"miter" );
182 return QStringLiteral(
"round" );
184 return QStringLiteral(
"???" );
190 const QString cleaned = str.toLower().trimmed();
191 if ( cleaned == QLatin1String(
"bevel" ) )
192 return Qt::BevelJoin;
193 if ( cleaned == QLatin1String(
"miter" ) )
194 return Qt::MiterJoin;
195 if ( cleaned == QLatin1String(
"round" ) )
196 return Qt::RoundJoin;
197 return Qt::BevelJoin;
205 return QStringLiteral(
"bevel" );
207 return QStringLiteral(
"mitre" );
209 return QStringLiteral(
"round" );
217 if ( str == QLatin1String(
"bevel" ) )
return Qt::BevelJoin;
218 if ( str == QLatin1String(
"mitre" ) )
return Qt::MiterJoin;
219 if ( str == QLatin1String(
"round" ) )
return Qt::RoundJoin;
220 return Qt::BevelJoin;
228 return QStringLiteral(
"square" );
230 return QStringLiteral(
"flat" );
232 return QStringLiteral(
"round" );
234 return QStringLiteral(
"???" );
240 if ( str == QLatin1String(
"square" ) )
return Qt::SquareCap;
241 if ( str == QLatin1String(
"flat" ) )
return Qt::FlatCap;
242 if ( str == QLatin1String(
"round" ) )
return Qt::RoundCap;
243 return Qt::SquareCap;
251 return QStringLiteral(
"square" );
253 return QStringLiteral(
"butt" );
255 return QStringLiteral(
"round" );
263 if ( str == QLatin1String(
"square" ) )
return Qt::SquareCap;
264 if ( str == QLatin1String(
"butt" ) )
return Qt::FlatCap;
265 if ( str == QLatin1String(
"round" ) )
return Qt::RoundCap;
266 return Qt::SquareCap;
273 case Qt::SolidPattern :
274 return QStringLiteral(
"solid" );
275 case Qt::HorPattern :
276 return QStringLiteral(
"horizontal" );
277 case Qt::VerPattern :
278 return QStringLiteral(
"vertical" );
279 case Qt::CrossPattern :
280 return QStringLiteral(
"cross" );
281 case Qt::BDiagPattern :
282 return QStringLiteral(
"b_diagonal" );
283 case Qt::FDiagPattern :
284 return QStringLiteral(
"f_diagonal" );
285 case Qt::DiagCrossPattern :
286 return QStringLiteral(
"diagonal_x" );
287 case Qt::Dense1Pattern :
288 return QStringLiteral(
"dense1" );
289 case Qt::Dense2Pattern :
290 return QStringLiteral(
"dense2" );
291 case Qt::Dense3Pattern :
292 return QStringLiteral(
"dense3" );
293 case Qt::Dense4Pattern :
294 return QStringLiteral(
"dense4" );
295 case Qt::Dense5Pattern :
296 return QStringLiteral(
"dense5" );
297 case Qt::Dense6Pattern :
298 return QStringLiteral(
"dense6" );
299 case Qt::Dense7Pattern :
300 return QStringLiteral(
"dense7" );
302 return QStringLiteral(
"no" );
304 return QStringLiteral(
"???" );
310 if ( str == QLatin1String(
"solid" ) )
return Qt::SolidPattern;
311 if ( str == QLatin1String(
"horizontal" ) )
return Qt::HorPattern;
312 if ( str == QLatin1String(
"vertical" ) )
return Qt::VerPattern;
313 if ( str == QLatin1String(
"cross" ) )
return Qt::CrossPattern;
314 if ( str == QLatin1String(
"b_diagonal" ) )
return Qt::BDiagPattern;
315 if ( str == QLatin1String(
"f_diagonal" ) )
return Qt::FDiagPattern;
316 if ( str == QLatin1String(
"diagonal_x" ) )
return Qt::DiagCrossPattern;
317 if ( str == QLatin1String(
"dense1" ) )
return Qt::Dense1Pattern;
318 if ( str == QLatin1String(
"dense2" ) )
return Qt::Dense2Pattern;
319 if ( str == QLatin1String(
"dense3" ) )
return Qt::Dense3Pattern;
320 if ( str == QLatin1String(
"dense4" ) )
return Qt::Dense4Pattern;
321 if ( str == QLatin1String(
"dense5" ) )
return Qt::Dense5Pattern;
322 if ( str == QLatin1String(
"dense6" ) )
return Qt::Dense6Pattern;
323 if ( str == QLatin1String(
"dense7" ) )
return Qt::Dense7Pattern;
324 if ( str == QLatin1String(
"no" ) )
return Qt::NoBrush;
325 return Qt::SolidPattern;
332 case Qt::CrossPattern:
333 return QStringLiteral(
"cross" );
334 case Qt::DiagCrossPattern:
335 return QStringLiteral(
"x" );
342 return QStringLiteral(
"horline" );
344 return QStringLiteral(
"line" );
345 case Qt::BDiagPattern:
346 return QStringLiteral(
"slash" );
347 case Qt::FDiagPattern:
348 return QStringLiteral(
"backslash" );
351 case Qt::Dense1Pattern:
352 case Qt::Dense2Pattern:
353 case Qt::Dense3Pattern:
354 case Qt::Dense4Pattern:
355 case Qt::Dense5Pattern:
356 case Qt::Dense6Pattern:
357 case Qt::Dense7Pattern:
367 if ( str == QLatin1String(
"horline" ) )
return Qt::HorPattern;
368 if ( str == QLatin1String(
"line" ) )
return Qt::VerPattern;
369 if ( str == QLatin1String(
"cross" ) )
return Qt::CrossPattern;
370 if ( str == QLatin1String(
"slash" ) )
return Qt::BDiagPattern;
371 if ( str == QLatin1String(
"backshash" ) )
return Qt::FDiagPattern;
372 if ( str == QLatin1String(
"x" ) )
return Qt::DiagCrossPattern;
374 if ( str.startsWith( QLatin1String(
"brush://" ) ) )
386 QString s = value.toString().toLower().trimmed();
387 if ( s == QLatin1String(
"single" ) )
389 else if ( s == QLatin1String(
"reversed" ) )
391 else if ( s == QLatin1String(
"double" ) )
393 else if ( value.toInt() == 1 )
395 else if ( value.toInt() == 2 )
397 else if ( value.toInt( &intOk ) == 0 && intOk )
411 QString s = value.toString().toLower().trimmed();
412 if ( s == QLatin1String(
"plain" ) )
414 else if ( s == QLatin1String(
"lefthalf" ) )
416 else if ( s == QLatin1String(
"righthalf" ) )
418 else if ( value.toInt() == 1 )
420 else if ( value.toInt() == 2 )
422 else if ( value.toInt( &intOk ) == 0 && intOk )
437 QStringList lst = str.split(
',' );
438 if ( lst.count() != 2 )
439 return QPointF( 0, 0 );
440 return QPointF( lst[0].toDouble(), lst[1].toDouble() );
448 if ( value.isNull() )
451 if ( value.type() == QVariant::List )
453 const QVariantList list = value.toList();
454 if ( list.size() != 2 )
458 bool convertOk =
false;
459 double x = list.at( 0 ).toDouble( &convertOk );
462 double y = list.at( 1 ).toDouble( &convertOk );
467 return QPointF( x, y );
475 const QStringList list = value.toString().trimmed().split(
',' );
476 if ( list.count() != 2 )
478 bool convertOk =
false;
479 double x = list.at( 0 ).toDouble( &convertOk );
482 double y = list.at( 1 ).toDouble( &convertOk );
487 return QPointF( x, y );
501 QStringList lst =
string.split(
',' );
502 if ( lst.count() != 2 )
503 return QSizeF( 0, 0 );
504 return QSizeF( lst[0].toDouble(), lst[1].toDouble() );
512 if ( value.isNull() )
515 if ( value.type() == QVariant::List )
517 const QVariantList list = value.toList();
518 if ( list.size() != 2 )
522 bool convertOk =
false;
523 double x = list.at( 0 ).toDouble( &convertOk );
526 double y = list.at( 1 ).toDouble( &convertOk );
531 return QSizeF( x, y );
539 const QStringList list = value.toString().trimmed().split(
',' );
540 if ( list.count() != 2 )
542 bool convertOk =
false;
543 double x = list.at( 0 ).toDouble( &convertOk );
546 double y = list.at( 1 ).toDouble( &convertOk );
551 return QSizeF( x, y );
572 if ( str.startsWith( QLatin1String(
"3x:" ) ) )
575 QString chopped = str.mid( 3 );
576 lst = chopped.split(
',' );
580 lst = str.split(
',' );
582 if ( lst.count() < 2 )
585 double minScale = lst[0].toDouble();
587 minScale = minScale != 0 ? 1.0 / minScale : 0;
588 double maxScale = lst[1].toDouble();
590 maxScale = maxScale != 0 ? 1.0 / maxScale : 0;
592 if ( lst.count() < 6 )
612 *scaleFactor = 0.001;
613 return QStringLiteral(
"http://www.opengeospatial.org/se/units/metre" );
620 *scaleFactor = 1 / 0.28;
629 if ( str == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
632 *scaleFactor = 1000.0;
635 else if ( str == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
638 *scaleFactor = 304.8;
641 else if ( str == QLatin1String(
"http://www.opengeospatial.org/se/units/pixel" ) )
651 *scaleFactor = 1 / 0.00028;
657 QString vectorString;
658 QVector<qreal>::const_iterator it = v.constBegin();
659 for ( ; it != v.constEnd(); ++it )
661 if ( it != v.constBegin() )
663 vectorString.append(
';' );
665 vectorString.append( QString::number( *it ) );
672 QVector<qreal> resultVector;
674 QStringList realList = s.split(
';' );
675 QStringList::const_iterator it = realList.constBegin();
676 for ( ; it != realList.constEnd(); ++it )
678 resultVector.append( it->toDouble() );
686 QString vectorString;
687 QVector<qreal>::const_iterator it = v.constBegin();
688 for ( ; it != v.constEnd(); ++it )
690 if ( it != v.constBegin() )
692 vectorString.append(
' ' );
694 vectorString.append( QString::number( *it ) );
701 QVector<qreal> resultVector;
703 QStringList realList = s.split(
' ' );
704 QStringList::const_iterator it = realList.constBegin();
705 for ( ; it != realList.constEnd(); ++it )
707 resultVector.append( it->toDouble() );
715 QString encodedValue;
717 switch ( scaleMethod )
720 encodedValue = QStringLiteral(
"diameter" );
723 encodedValue = QStringLiteral(
"area" );
733 if ( str == QLatin1String(
"diameter" ) )
747 if ( s.compare( QLatin1String(
"Lighten" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Lighten;
748 if ( s.compare( QLatin1String(
"Screen" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Screen;
749 if ( s.compare( QLatin1String(
"Dodge" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorDodge;
750 if ( s.compare( QLatin1String(
"Addition" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Plus;
751 if ( s.compare( QLatin1String(
"Darken" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Darken;
752 if ( s.compare( QLatin1String(
"Multiply" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Multiply;
753 if ( s.compare( QLatin1String(
"Burn" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_ColorBurn;
754 if ( s.compare( QLatin1String(
"Overlay" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Overlay;
755 if ( s.compare( QLatin1String(
"SoftLight" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_SoftLight;
756 if ( s.compare( QLatin1String(
"HardLight" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_HardLight;
757 if ( s.compare( QLatin1String(
"Difference" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Difference;
758 if ( s.compare( QLatin1String(
"Subtract" ), Qt::CaseInsensitive ) == 0 )
return QPainter::CompositionMode_Exclusion;
759 return QPainter::CompositionMode_SourceOver;
764 return QIcon(
symbolPreviewPixmap( symbol, size, padding,
nullptr,
false,
nullptr, shape ) );
770 QPixmap pixmap( size );
771 pixmap.fill( Qt::transparent );
773 painter.begin( &pixmap );
777 painter.setRenderHint( QPainter::Antialiasing );
786 size.setWidth( size.rwidth() - ( padding * 2 ) );
787 size.setHeight( size.rheight() - ( padding * 2 ) );
788 painter.translate( padding, padding );
798 std::unique_ptr<QgsSymbol> symbol_noDD( symbol->
clone( ) );
800 for (
const auto &layer : layers )
802 for (
int i = 0; i < layer->dataDefinedProperties().count(); ++i )
804 QgsProperty &prop = layer->dataDefinedProperties().property( i );
810 symbol_noDD->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape );
814 std::unique_ptr<QgsSymbol> symbolClone( symbol->
clone( ) );
815 symbolClone->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape );
829 maxBleed = layerMaxBleed > maxBleed ? layerMaxBleed : maxBleed;
839 painter.begin( &picture );
840 painter.setRenderHint( QPainter::Antialiasing );
844 QgsSymbolRenderContext symbolContext( renderContext, units, 1.0,
false, QgsSymbol::RenderHints(),
nullptr );
845 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
846 layerClone->drawPreviewIcon( symbolContext, size );
853 QPixmap pixmap( size );
854 pixmap.fill( Qt::transparent );
856 painter.begin( &pixmap );
857 painter.setRenderHint( QPainter::Antialiasing );
866 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
867 layerClone->drawPreviewIcon( symbolContext, size );
869 return QIcon( pixmap );
879 QPixmap pixmap( size );
880 pixmap.fill( Qt::transparent );
883 painter.begin( &pixmap );
886 drawStippledBackground( &painter, QRect( padding, padding, size.width() - padding * 2, size.height() - padding * 2 ) );
890 for (
int i = 0; i < size.width(); i++ )
892 QPen pen( ramp->
color(
static_cast< double >( i ) / size.width() ) );
893 painter.setPen( pen );
894 painter.drawLine( i, 0 + padding, i, size.height() - 1 - padding );
903 uchar pixDataRGB[] = { 255, 255, 255, 255,
908 QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
910 int width = ( rect.width() < rect.height() ) ?
911 rect.width() / 2.5 : rect.height() / 2.5;
912 QPixmap pix = QPixmap::fromImage( img.scaled( width, width ) );
915 brush.setTexture( pix );
916 painter->fillRect( rect, brush );
921 qreal s = ( markerSize - 1 ) / 2.0;
926 p.setPen( QColor( 50, 100, 120, 200 ) );
927 p.setBrush( QColor( 200, 200, 210, 120 ) );
928 p.drawEllipse( x - s, y - s, s * 2, s * 2 );
931 p.setPen( QColor( 255, 0, 0 ) );
932 p.drawLine( x - s, y + s, x + s, y - s );
933 p.drawLine( x - s, y - s, x + s, y + s );
945 static QPolygonF makeOffsetGeometry(
const QgsPolylineXY &polyline )
947 int i, pointCount = polyline.count();
949 QPolygonF resultLine;
950 resultLine.resize( pointCount );
954 for ( i = 0; i < pointCount; ++i, tempPtr++ )
955 resultLine[i] = QPointF( tempPtr->
x(), tempPtr->
y() );
959 static QList<QPolygonF> makeOffsetGeometry(
const QgsPolygonXY &polygon )
961 QList<QPolygonF> resultGeom;
962 resultGeom.reserve( polygon.size() );
963 for (
int ring = 0; ring < polygon.size(); ++ring )
964 resultGeom.append( makeOffsetGeometry( polygon[ ring ] ) );
970 QList<QPolygonF> resultLine;
972 if ( polyline.count() < 2 )
974 resultLine.append( polyline );
978 unsigned int i, pointCount = polyline.count();
981 QPointF *tempPtr = polyline.data();
982 for ( i = 0; i < pointCount; ++i, tempPtr++ )
983 tempPolyline[i] =
QgsPointXY( tempPtr->rx(), tempPtr->ry() );
986 if ( !tempGeometry.
isNull() )
988 int quadSegments = 0;
989 double miterLimit = 2.0;
997 if ( !offsetGeom.
isNull() )
999 tempGeometry = offsetGeom;
1004 resultLine.append( makeOffsetGeometry( line ) );
1009 resultLine.append( makeOffsetGeometry( tempGeometry.
asPolygon() ) );
1015 resultLine.reserve( tempMPolyline.count() );
1016 for (
int part = 0; part < tempMPolyline.count(); ++part )
1018 resultLine.append( makeOffsetGeometry( tempMPolyline[ part ] ) );
1025 resultLine.reserve( tempMPolygon.count() );
1026 for (
int part = 0; part < tempMPolygon.count(); ++part )
1028 resultLine.append( makeOffsetGeometry( tempMPolygon[ part ] ) );
1036 resultLine.append( polyline );
1046 QDomNode layerNode = element.firstChild();
1048 while ( !layerNode.isNull() )
1050 QDomElement e = layerNode.toElement();
1053 if ( e.tagName() != QLatin1String(
"layer" ) )
1064 QDomElement s = e.firstChildElement( QStringLiteral(
"symbol" ) );
1071 QgsDebugMsg(
"symbol layer refused subsymbol: " + s.attribute(
"name" ) );
1074 layers.append( layer );
1078 layerNode = layerNode.nextSibling();
1081 if ( layers.isEmpty() )
1083 QgsDebugMsg( QStringLiteral(
"no layers for symbol" ) );
1087 QString symbolType = element.attribute( QStringLiteral(
"type" ) );
1090 if ( symbolType == QLatin1String(
"line" ) )
1092 else if ( symbolType == QLatin1String(
"fill" ) )
1094 else if ( symbolType == QLatin1String(
"marker" ) )
1098 QgsDebugMsg(
"unknown symbol type " + symbolType );
1102 if ( element.hasAttribute( QStringLiteral(
"outputUnit" ) ) )
1106 if ( element.hasAttribute( ( QStringLiteral(
"mapUnitScale" ) ) ) )
1109 double oldMin = element.attribute( QStringLiteral(
"mapUnitMinScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1110 mapUnitScale.
minScale = oldMin != 0 ? 1.0 / oldMin : 0;
1111 double oldMax = element.attribute( QStringLiteral(
"mapUnitMaxScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1112 mapUnitScale.
maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
1115 symbol->
setOpacity( element.attribute( QStringLiteral(
"alpha" ), QStringLiteral(
"1.0" ) ).toDouble() );
1116 symbol->
setClipFeaturesToExtent( element.attribute( QStringLiteral(
"clip_to_extent" ), QStringLiteral(
"1" ) ).toInt() );
1117 symbol->
setForceRHR( element.attribute( QStringLiteral(
"force_rhr" ), QStringLiteral(
"0" ) ).toInt() );
1123 QString layerClass = element.attribute( QStringLiteral(
"class" ) );
1124 bool locked = element.attribute( QStringLiteral(
"locked" ) ).toInt();
1125 bool enabled = element.attribute( QStringLiteral(
"enabled" ), QStringLiteral(
"1" ) ).toInt();
1126 int pass = element.attribute( QStringLiteral(
"pass" ) ).toInt();
1143 QDomElement effectElem = element.firstChildElement( QStringLiteral(
"effect" ) );
1144 if ( !effectElem.isNull() )
1152 QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1153 if ( !ddProps.isNull() )
1172 return QStringLiteral(
"line" );
1174 return QStringLiteral(
"marker" );
1176 return QStringLiteral(
"fill" );
1185 QDomElement symEl = doc.createElement( QStringLiteral(
"symbol" ) );
1186 symEl.setAttribute( QStringLiteral(
"type" ), _nameForSymbolType( symbol->
type() ) );
1187 symEl.setAttribute( QStringLiteral(
"name" ), name );
1188 symEl.setAttribute( QStringLiteral(
"alpha" ), QString::number( symbol->
opacity() ) );
1189 symEl.setAttribute( QStringLiteral(
"clip_to_extent" ), symbol->
clipFeaturesToExtent() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1190 symEl.setAttribute( QStringLiteral(
"force_rhr" ), symbol->
forceRHR() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1197 QDomElement layerEl = doc.createElement( QStringLiteral(
"layer" ) );
1198 layerEl.setAttribute( QStringLiteral(
"class" ), layer->
layerType() );
1199 layerEl.setAttribute( QStringLiteral(
"enabled" ), layer->
enabled() );
1200 layerEl.setAttribute( QStringLiteral(
"locked" ), layer->
isLocked() );
1201 layerEl.setAttribute( QStringLiteral(
"pass" ), layer->
renderingPass() );
1212 QDomElement ddProps = doc.createElement( QStringLiteral(
"data_defined_properties" ) );
1214 layerEl.appendChild( ddProps );
1218 QString subname = QStringLiteral(
"@%1@%2" ).arg( name ).arg( i );
1219 QDomElement subEl =
saveSymbol( subname, subSymbol, doc, context );
1220 layerEl.appendChild( subEl );
1222 symEl.appendChild( layerEl );
1230 QDomDocument doc( QStringLiteral(
"qgis-symbol-definition" ) );
1233 QTextStream stream( &props );
1234 symbolElem.save( stream, -1 );
1244 if ( element.isNull() )
1249 QString symbolizerName = element.localName();
1251 if ( symbolizerName == QLatin1String(
"PointSymbolizer" ) )
1254 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1255 if ( graphicElem.isNull() )
1257 QgsDebugMsg( QStringLiteral(
"Graphic element not found in PointSymbolizer" ) );
1293 if ( symbolizerName == QLatin1String(
"LineSymbolizer" ) )
1296 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1297 if ( strokeElem.isNull() )
1299 QgsDebugMsg( QStringLiteral(
"Stroke element not found in LineSymbolizer" ) );
1329 if ( symbolizerName == QLatin1String(
"PolygonSymbolizer" ) )
1332 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1333 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1334 if ( fillElem.isNull() && strokeElem.isNull() )
1336 QgsDebugMsg( QStringLiteral(
"neither Fill nor Stroke element not found in PolygonSymbolizer" ) );
1354 if ( l->
layerType() == QLatin1String(
"SimpleFill" ) || l->
layerType() == QLatin1String(
"SVGFill" ) )
1390 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1391 if ( fillElem.isNull() )
1393 QgsDebugMsg( QStringLiteral(
"Fill element not found" ) );
1413 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1414 if ( strokeElem.isNull() )
1416 QgsDebugMsg( QStringLiteral(
"Stroke element not found" ) );
1432 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1433 if ( graphicElem.isNull() )
1435 QgsDebugMsg( QStringLiteral(
"Graphic element not found" ) );
1455 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1456 if ( graphicElem.isNull() )
1459 QDomElement externalGraphicElem = graphicElem.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
1460 if ( externalGraphicElem.isNull() )
1464 QDomElement formatElem = externalGraphicElem.firstChildElement( QStringLiteral(
"Format" ) );
1465 if ( formatElem.isNull() )
1468 QString format = formatElem.firstChild().nodeValue();
1469 if ( format != QLatin1String(
"image/svg+xml" ) )
1471 QgsDebugMsg(
"unsupported External Graphic format found: " + format );
1476 QDomElement onlineResourceElem = externalGraphicElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1477 QDomElement inlineContentElem = externalGraphicElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1478 if ( !onlineResourceElem.isNull() )
1483 else if ( !inlineContentElem.isNull() )
1496 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1497 if ( graphicElem.isNull() )
1500 QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1501 if ( markElem.isNull() )
1504 QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
1505 return !wellKnownNameElem.isNull();
1511 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1512 if ( graphicElem.isNull() )
1515 QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1516 if ( markElem.isNull() )
1520 QDomElement formatElem = markElem.firstChildElement( QStringLiteral(
"Format" ) );
1521 if ( formatElem.isNull() )
1524 QString format = formatElem.firstChild().nodeValue();
1525 if ( format != QLatin1String(
"ttf" ) )
1527 QgsDebugMsg(
"unsupported Graphic Mark format found: " + format );
1532 QDomElement onlineResourceElem = markElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1533 QDomElement inlineContentElem = markElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1534 if ( !onlineResourceElem.isNull() )
1537 QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
1538 if ( !markIndexElem.isNull() )
1541 else if ( !inlineContentElem.isNull() )
1556 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1557 if ( graphicElem.isNull() )
1561 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
1563 if ( it.key() == QLatin1String(
"widthHeightFactor" ) )
1574 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1575 if ( strokeElem.isNull() )
1578 QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral(
"GraphicStroke" ) );
1579 if ( graphicStrokeElem.isNull() )
1587 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1588 if ( fillElem.isNull() )
1591 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1592 if ( graphicFillElem.isNull() )
1595 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1596 if ( graphicElem.isNull() )
1602 QColor fillColor, strokeColor;
1603 double size, strokeWidth;
1604 Qt::PenStyle strokeStyle;
1605 if ( !
wellKnownMarkerFromSld( graphicElem, name, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
1608 if ( name != QLatin1String(
"horline" ) )
1616 double angle = angleFunc.toDouble( &ok );
1628 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1629 if ( fillElem.isNull() )
1632 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1633 if ( graphicFillElem.isNull() )
1653 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1654 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1658 bool validFill =
false, validStroke =
false;
1663 Qt::BrushStyle fillStyle;
1665 if (
fillFromSld( fillElem, fillStyle, fillColor ) )
1671 Qt::PenStyle strokeStyle;
1672 double strokeWidth = 1.0, dashOffset = 0.0;
1673 QVector<qreal> customDashPattern;
1675 if (
lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth,
1676 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
1679 if ( validFill || validStroke )
1682 map[QStringLiteral(
"name" )] = QStringLiteral(
"square" );
1683 map[QStringLiteral(
"color" )] =
encodeColor( validFill ? fillColor : Qt::transparent );
1684 map[QStringLiteral(
"color_border" )] =
encodeColor( validStroke ? strokeColor : Qt::transparent );
1685 map[QStringLiteral(
"size" )] = QString::number( 6 );
1686 map[QStringLiteral(
"angle" )] = QString::number( 0 );
1687 map[QStringLiteral(
"offset" )] =
encodePoint( QPointF( 0, 0 ) );
1694 bool validFill =
false, validStroke =
false;
1697 QString name, format;
1699 QColor fillColor, strokeColor;
1700 double strokeWidth = 1.0, size = 0.0,
angle = 0.0;
1704 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1705 if ( !graphicFillElem.isNull() )
1708 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1709 if ( !graphicElem.isNull() )
1715 QDomElement graphicChildElem = graphicElem.firstChildElement();
1716 while ( !graphicChildElem.isNull() )
1718 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
1721 QDomElement wellKnownNameElem = graphicChildElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
1722 if ( !wellKnownNameElem.isNull() )
1724 name = wellKnownNameElem.firstChild().nodeValue();
1730 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) || graphicChildElem.localName() == QLatin1String(
"Mark" ) )
1733 QDomElement formatElem = graphicChildElem.firstChildElement( QStringLiteral(
"Format" ) );
1734 if ( formatElem.isNull() )
1737 format = formatElem.firstChild().nodeValue();
1741 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) && format != QLatin1String(
"image/svg+xml" ) )
1746 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format != QLatin1String(
"ttf" ) )
1750 QDomElement onlineResourceElem = graphicChildElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1751 QDomElement inlineContentElem = graphicChildElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1753 if ( !onlineResourceElem.isNull() )
1755 name = onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) );
1757 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format == QLatin1String(
"ttf" ) )
1760 if ( name.startsWith( QLatin1String(
"ttf://" ) ) )
1761 name = name.mid( 6 );
1764 QDomElement markIndexElem = graphicChildElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
1765 if ( markIndexElem.isNull() )
1769 int v = markIndexElem.firstChild().nodeValue().toInt( &ok );
1780 else if ( !inlineContentElem.isNull() )
1790 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
1792 name = QStringLiteral(
"square" );
1799 if ( found && graphicChildElem.localName() == QLatin1String(
"Mark" ) )
1806 Qt::BrushStyle markFillStyle;
1808 QDomElement markFillElem = graphicChildElem.firstChildElement( QStringLiteral(
"Fill" ) );
1809 if (
fillFromSld( markFillElem, markFillStyle, fillColor ) )
1814 Qt::PenStyle strokeStyle;
1815 double strokeWidth = 1.0, dashOffset = 0.0;
1816 QVector<qreal> customDashPattern;
1818 QDomElement markStrokeElem = graphicChildElem.firstChildElement( QStringLiteral(
"Stroke" ) );
1819 if (
lineFromSld( markStrokeElem, strokeStyle, strokeColor, strokeWidth,
1820 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
1827 QDomElement opacityElem = graphicElem.firstChildElement( QStringLiteral(
"Opacity" ) );
1828 if ( !opacityElem.isNull() )
1829 fillColor.setAlpha(
decodeSldAlpha( opacityElem.firstChild().nodeValue() ) );
1831 QDomElement sizeElem = graphicElem.firstChildElement( QStringLiteral(
"Size" ) );
1832 if ( !sizeElem.isNull() )
1835 double v = sizeElem.firstChild().nodeValue().toDouble( &ok );
1844 double v = angleFunc.toDouble( &ok );
1854 if ( validFill || validStroke )
1856 if ( format == QLatin1String(
"image/svg+xml" ) )
1859 map[QStringLiteral(
"name" )] = name;
1860 map[QStringLiteral(
"fill" )] = fillColor.name();
1861 map[QStringLiteral(
"outline" )] = strokeColor.name();
1862 map[QStringLiteral(
"outline-width" )] = QString::number( strokeWidth );
1864 map[QStringLiteral(
"size" )] = QString::number( size );
1866 map[QStringLiteral(
"angle" )] = QString::number(
angle );
1867 if ( !offset.isNull() )
1868 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
1871 else if ( format == QLatin1String(
"ttf" ) )
1874 map[QStringLiteral(
"font" )] = name;
1875 map[QStringLiteral(
"chr" )] = markIndex;
1876 map[QStringLiteral(
"color" )] =
encodeColor( validFill ? fillColor : Qt::transparent );
1878 map[QStringLiteral(
"size" )] = QString::number( size );
1880 map[QStringLiteral(
"angle" )] = QString::number(
angle );
1881 if ( !offset.isNull() )
1882 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
1888 if ( layers.isEmpty() )
1891 layerList << layers;
1898 QString patternName;
1899 switch ( brushStyle )
1904 case Qt::SolidPattern:
1905 if ( color.isValid() )
1908 if ( color.alpha() < 255 )
1913 case Qt::CrossPattern:
1914 case Qt::DiagCrossPattern:
1915 case Qt::HorPattern:
1916 case Qt::VerPattern:
1917 case Qt::BDiagPattern:
1918 case Qt::FDiagPattern:
1919 case Qt::Dense1Pattern:
1920 case Qt::Dense2Pattern:
1921 case Qt::Dense3Pattern:
1922 case Qt::Dense4Pattern:
1923 case Qt::Dense5Pattern:
1924 case Qt::Dense6Pattern:
1925 case Qt::Dense7Pattern:
1930 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( brushStyle ) ) );
1934 QDomElement graphicFillElem = doc.createElement( QStringLiteral(
"se:GraphicFill" ) );
1935 element.appendChild( graphicFillElem );
1937 QDomElement graphicElem = doc.createElement( QStringLiteral(
"se:Graphic" ) );
1938 graphicFillElem.appendChild( graphicElem );
1940 QColor fillColor = patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
1941 QColor strokeColor = !patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
1944 wellKnownMarkerToSld( doc, graphicElem, patternName, fillColor, strokeColor, Qt::SolidLine, -1, -1 );
1951 brushStyle = Qt::SolidPattern;
1952 color = QColor( 128, 128, 128 );
1954 if ( element.isNull() )
1956 brushStyle = Qt::NoBrush;
1961 QDomElement graphicFillElem = element.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1963 if ( graphicFillElem.isNull() )
1966 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
1968 QgsDebugMsg( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ) );
1970 if ( it.key() == QLatin1String(
"fill" ) )
1971 color = QColor( it.value() );
1972 else if ( it.key() == QLatin1String(
"fill-opacity" ) )
1978 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1979 if ( graphicElem.isNull() )
1982 QString patternName = QStringLiteral(
"square" );
1983 QColor fillColor, strokeColor;
1984 double strokeWidth, size;
1985 Qt::PenStyle strokeStyle;
1986 if ( !
wellKnownMarkerFromSld( graphicElem, patternName, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
1990 if ( brushStyle == Qt::NoBrush )
1993 QColor
c = patternName.startsWith( QLatin1String(
"brush://" ) ) ? fillColor : strokeColor;
2002 Qt::PenStyle penStyle,
const QColor &color,
double width,
2003 const Qt::PenJoinStyle *penJoinStyle,
const Qt::PenCapStyle *penCapStyle,
2004 const QVector<qreal> *customDashPattern,
double dashOffset )
2006 QVector<qreal> dashPattern;
2007 const QVector<qreal> *pattern = &dashPattern;
2009 if ( penStyle == Qt::CustomDashLine && !customDashPattern )
2011 element.appendChild( doc.createComment( QStringLiteral(
"WARNING: Custom dash pattern required but not provided. Using default dash pattern." ) ) );
2012 penStyle = Qt::DashLine;
2024 dashPattern.push_back( 4.0 );
2025 dashPattern.push_back( 2.0 );
2028 dashPattern.push_back( 1.0 );
2029 dashPattern.push_back( 2.0 );
2031 case Qt::DashDotLine:
2032 dashPattern.push_back( 4.0 );
2033 dashPattern.push_back( 2.0 );
2034 dashPattern.push_back( 1.0 );
2035 dashPattern.push_back( 2.0 );
2037 case Qt::DashDotDotLine:
2038 dashPattern.push_back( 4.0 );
2039 dashPattern.push_back( 2.0 );
2040 dashPattern.push_back( 1.0 );
2041 dashPattern.push_back( 2.0 );
2042 dashPattern.push_back( 1.0 );
2043 dashPattern.push_back( 2.0 );
2046 case Qt::CustomDashLine:
2047 Q_ASSERT( customDashPattern );
2048 pattern = customDashPattern;
2052 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( penStyle ) ) );
2056 if ( color.isValid() )
2059 if ( color.alpha() < 255 )
2066 else if ( width == 0 )
2076 if ( !pattern->isEmpty() )
2086 Qt::PenStyle &penStyle, QColor &color,
double &width,
2087 Qt::PenJoinStyle *penJoinStyle, Qt::PenCapStyle *penCapStyle,
2088 QVector<qreal> *customDashPattern,
double *dashOffset )
2092 penStyle = Qt::SolidLine;
2093 color = QColor( 0, 0, 0 );
2096 *penJoinStyle = Qt::BevelJoin;
2098 *penCapStyle = Qt::SquareCap;
2099 if ( customDashPattern )
2100 customDashPattern->clear();
2104 if ( element.isNull() )
2106 penStyle = Qt::NoPen;
2112 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2114 QgsDebugMsg( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ) );
2116 if ( it.key() == QLatin1String(
"stroke" ) )
2118 color = QColor( it.value() );
2120 else if ( it.key() == QLatin1String(
"stroke-opacity" ) )
2124 else if ( it.key() == QLatin1String(
"stroke-width" ) )
2127 double w = it.value().toDouble( &ok );
2131 else if ( it.key() == QLatin1String(
"stroke-linejoin" ) && penJoinStyle )
2135 else if ( it.key() == QLatin1String(
"stroke-linecap" ) && penCapStyle )
2139 else if ( it.key() == QLatin1String(
"stroke-dasharray" ) )
2142 if ( !dashPattern.isEmpty() )
2146 bool dashPatternFound =
false;
2148 if ( dashPattern.count() == 2 )
2150 if ( dashPattern.at( 0 ) == 4.0 &&
2151 dashPattern.at( 1 ) == 2.0 )
2153 penStyle = Qt::DashLine;
2154 dashPatternFound =
true;
2156 else if ( dashPattern.at( 0 ) == 1.0 &&
2157 dashPattern.at( 1 ) == 2.0 )
2159 penStyle = Qt::DotLine;
2160 dashPatternFound =
true;
2163 else if ( dashPattern.count() == 4 )
2165 if ( dashPattern.at( 0 ) == 4.0 &&
2166 dashPattern.at( 1 ) == 2.0 &&
2167 dashPattern.at( 2 ) == 1.0 &&
2168 dashPattern.at( 3 ) == 2.0 )
2170 penStyle = Qt::DashDotLine;
2171 dashPatternFound =
true;
2174 else if ( dashPattern.count() == 6 )
2176 if ( dashPattern.at( 0 ) == 4.0 &&
2177 dashPattern.at( 1 ) == 2.0 &&
2178 dashPattern.at( 2 ) == 1.0 &&
2179 dashPattern.at( 3 ) == 2.0 &&
2180 dashPattern.at( 4 ) == 1.0 &&
2181 dashPattern.at( 5 ) == 2.0 )
2183 penStyle = Qt::DashDotDotLine;
2184 dashPatternFound =
true;
2189 if ( !dashPatternFound )
2191 if ( customDashPattern )
2193 penStyle = Qt::CustomDashLine;
2194 *customDashPattern = dashPattern;
2198 QgsDebugMsg( QStringLiteral(
"custom dash pattern required but not provided. Using default dash pattern." ) );
2199 penStyle = Qt::DashLine;
2204 else if ( it.key() == QLatin1String(
"stroke-dashoffset" ) && dashOffset )
2207 double d = it.value().toDouble( &ok );
2217 const QString &path,
const QString &mime,
2218 const QColor &color,
double size )
2220 QDomElement externalGraphicElem = doc.createElement( QStringLiteral(
"se:ExternalGraphic" ) );
2221 element.appendChild( externalGraphicElem );
2230 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2232 element.appendChild( sizeElem );
2237 const QString &path,
const QColor &fillColor,
double size,
const QColor &strokeColor,
double strokeWidth )
2244 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Parametric SVG" ) ) );
2248 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Plain SVG fallback, no parameters" ) ) );
2251 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Well known marker fallback" ) ) );
2257 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2259 graphicElem.appendChild( sizeElem );
2267 if ( fillColor.isValid() )
2269 url.addQueryItem( QStringLiteral(
"fill" ), fillColor.name() );
2270 url.addQueryItem( QStringLiteral(
"fill-opacity" ),
encodeSldAlpha( fillColor.alpha() ) );
2274 url.addQueryItem( QStringLiteral(
"fill" ), QStringLiteral(
"#000000" ) );
2275 url.addQueryItem( QStringLiteral(
"fill-opacity" ), QStringLiteral(
"1" ) );
2277 if ( strokeColor.isValid() )
2279 url.addQueryItem( QStringLiteral(
"outline" ), strokeColor.name() );
2280 url.addQueryItem( QStringLiteral(
"outline-opacity" ),
encodeSldAlpha( strokeColor.alpha() ) );
2284 url.addQueryItem( QStringLiteral(
"outline" ), QStringLiteral(
"#000000" ) );
2285 url.addQueryItem( QStringLiteral(
"outline-opacity" ), QStringLiteral(
"1" ) );
2287 url.addQueryItem( QStringLiteral(
"outline-width" ), QString::number( strokeWidth ) );
2288 QString params = url.toString( QUrl::FullyEncoded );
2289 if ( params.isEmpty() )
2295 return basePath +
"?" + params;
2300 QString &path, QString &mime,
2301 QColor &color,
double &size )
2306 QDomElement externalGraphicElem = element.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
2307 if ( externalGraphicElem.isNull() )
2312 QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2313 if ( !sizeElem.isNull() )
2316 double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2325 const QString &path,
const QString &format,
int *markIndex,
2326 const QColor &color,
double size )
2328 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2329 element.appendChild( markElem );
2335 QDomElement markIndexElem = doc.createElement( QStringLiteral(
"se:MarkIndex" ) );
2336 markIndexElem.appendChild( doc.createTextNode( QString::number( *markIndex ) ) );
2337 markElem.appendChild( markIndexElem );
2341 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2342 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2343 markElem.appendChild( fillElem );
2348 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2350 element.appendChild( sizeElem );
2355 QString &path, QString &format,
int &markIndex,
2356 QColor &color,
double &size )
2364 QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2365 if ( markElem.isNull() )
2370 QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
2371 if ( !markIndexElem.isNull() )
2374 int i = markIndexElem.firstChild().nodeValue().toInt( &ok );
2380 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2381 Qt::BrushStyle b = Qt::SolidPattern;
2386 QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2387 if ( !sizeElem.isNull() )
2390 double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2399 const QString &name,
const QColor &color,
const QColor &strokeColor, Qt::PenStyle strokeStyle,
2400 double strokeWidth,
double size )
2402 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2403 element.appendChild( markElem );
2405 QDomElement wellKnownNameElem = doc.createElement( QStringLiteral(
"se:WellKnownName" ) );
2406 wellKnownNameElem.appendChild( doc.createTextNode( name ) );
2407 markElem.appendChild( wellKnownNameElem );
2410 if ( color.isValid() )
2412 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2413 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2414 markElem.appendChild( fillElem );
2418 if ( strokeColor.isValid() )
2420 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
2421 lineToSld( doc, strokeElem, strokeStyle, strokeColor, strokeWidth );
2422 markElem.appendChild( strokeElem );
2428 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2430 element.appendChild( sizeElem );
2435 QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle,
2436 double &strokeWidth,
double &size )
2440 name = QStringLiteral(
"square" );
2442 strokeColor = QColor( 0, 0, 0 );
2446 QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2447 if ( markElem.isNull() )
2450 QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
2451 if ( !wellKnownNameElem.isNull() )
2453 name = wellKnownNameElem.firstChild().nodeValue();
2454 QgsDebugMsg(
"found Mark with well known name: " + name );
2458 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2459 Qt::BrushStyle b = Qt::SolidPattern;
2464 QDomElement strokeElem = markElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2465 lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth );
2469 QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2470 if ( !sizeElem.isNull() )
2473 double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2483 if ( !rotationFunc.isEmpty() )
2485 QDomElement rotationElem = doc.createElement( QStringLiteral(
"se:Rotation" ) );
2487 element.appendChild( rotationElem );
2493 QDomElement rotationElem = element.firstChildElement( QStringLiteral(
"Rotation" ) );
2494 if ( !rotationElem.isNull() )
2504 if ( !alphaFunc.isEmpty() )
2506 QDomElement opacityElem = doc.createElement( QStringLiteral(
"se:Opacity" ) );
2508 element.appendChild( opacityElem );
2514 QDomElement opacityElem = element.firstChildElement( QStringLiteral(
"Opacity" ) );
2515 if ( !opacityElem.isNull() )
2524 if ( offset.isNull() )
2527 QDomElement displacementElem = doc.createElement( QStringLiteral(
"se:Displacement" ) );
2528 element.appendChild( displacementElem );
2530 QDomElement dispXElem = doc.createElement( QStringLiteral(
"se:DisplacementX" ) );
2531 dispXElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.x(), 2 ) ) );
2533 QDomElement dispYElem = doc.createElement( QStringLiteral(
"se:DisplacementY" ) );
2534 dispYElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.y(), 2 ) ) );
2536 displacementElem.appendChild( dispXElem );
2537 displacementElem.appendChild( dispYElem );
2544 QDomElement anchorElem = doc.createElement( QStringLiteral(
"se:AnchorPoint" ) );
2545 element.appendChild( anchorElem );
2547 QDomElement anchorXElem = doc.createElement( QStringLiteral(
"se:AnchorPointX" ) );
2548 anchorXElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.x() ) ) );
2550 QDomElement anchorYElem = doc.createElement( QStringLiteral(
"se:AnchorPointY" ) );
2551 anchorYElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.y() ) ) );
2553 anchorElem.appendChild( anchorXElem );
2554 anchorElem.appendChild( anchorYElem );
2559 offset = QPointF( 0, 0 );
2561 QDomElement displacementElem = element.firstChildElement( QStringLiteral(
"Displacement" ) );
2562 if ( displacementElem.isNull() )
2565 QDomElement dispXElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementX" ) );
2566 if ( !dispXElem.isNull() )
2569 double offsetX = dispXElem.firstChild().nodeValue().toDouble( &ok );
2571 offset.setX( offsetX );
2574 QDomElement dispYElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementY" ) );
2575 if ( !dispYElem.isNull() )
2578 double offsetY = dispYElem.firstChild().nodeValue().toDouble( &ok );
2580 offset.setY( offsetY );
2587 const QString &label,
const QFont &font,
2588 const QColor &color,
double size )
2590 QDomElement labelElem = doc.createElement( QStringLiteral(
"se:Label" ) );
2591 labelElem.appendChild( doc.createTextNode( label ) );
2592 element.appendChild( labelElem );
2594 QDomElement fontElem = doc.createElement( QStringLiteral(
"se:Font" ) );
2595 element.appendChild( fontElem );
2599 fontElem.appendChild( createSldParameterElement( doc,
"font-style",
encodeSldFontStyle( font.style() ) ) );
2600 fontElem.appendChild( createSldParameterElement( doc,
"font-weight",
encodeSldFontWeight( font.weight() ) ) );
2605 if ( color.isValid() )
2607 QDomElement fillElem = doc.createElement( QStringLiteral(
"Fill" ) );
2608 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2609 element.appendChild( fillElem );
2614 Qt::PenJoinStyle joinStyle,
2615 Qt::PenCapStyle capStyle,
2617 const QVector<qreal> *dashPattern )
2620 penStyle.append(
"PEN(" );
2621 penStyle.append(
"c:" );
2622 penStyle.append(
c.name() );
2623 penStyle.append(
",w:" );
2625 penStyle.append( QString::number( width * mmScaleFactor ) );
2626 penStyle.append(
"mm" );
2629 if ( dashPattern && !dashPattern->isEmpty() )
2631 penStyle.append(
",p:\"" );
2632 QVector<qreal>::const_iterator pIt = dashPattern->constBegin();
2633 for ( ; pIt != dashPattern->constEnd(); ++pIt )
2635 if ( pIt != dashPattern->constBegin() )
2637 penStyle.append(
' ' );
2639 penStyle.append( QString::number( *pIt * mapUnitScaleFactor ) );
2640 penStyle.append(
'g' );
2642 penStyle.append(
'\"' );
2646 penStyle.append(
",cap:" );
2650 penStyle.append(
'p' );
2653 penStyle.append(
'r' );
2657 penStyle.append(
'b' );
2661 penStyle.append(
",j:" );
2662 switch ( joinStyle )
2665 penStyle.append(
'b' );
2668 penStyle.append(
'r' );
2672 penStyle.append(
'm' );
2678 penStyle.append(
",dp:" );
2679 penStyle.append( QString::number( offset * mapUnitScaleFactor ) );
2680 penStyle.append(
'g' );
2683 penStyle.append(
')' );
2690 brushStyle.append(
"BRUSH(" );
2691 brushStyle.append(
"fc:" );
2692 brushStyle.append( fillColor.name() );
2693 brushStyle.append(
')' );
2699 if ( geomFunc.isEmpty() )
2702 QDomElement geometryElem = doc.createElement( QStringLiteral(
"Geometry" ) );
2703 element.appendChild( geometryElem );
2733 QDomElement geometryElem = element.firstChildElement( QStringLiteral(
"Geometry" ) );
2734 if ( geometryElem.isNull() )
2746 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " +
function ) );
2750 if ( !filterElem.isNull() )
2751 element.appendChild( filterElem );
2762 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " +
function ) );
2766 if ( !filterElem.isNull() )
2767 element.appendChild( filterElem );
2774 QDomElement elem = element;
2775 if ( element.tagName() != QLatin1String(
"Filter" ) )
2777 QDomNodeList filterNodes = element.elementsByTagName( QStringLiteral(
"Filter" ) );
2778 if ( !filterNodes.isEmpty() )
2780 elem = filterNodes.at( 0 ).toElement();
2784 if ( elem.isNull() )
2809 const QString &path,
const QString &format )
2813 QDomElement onlineResourceElem = doc.createElement( QStringLiteral(
"se:OnlineResource" ) );
2814 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
2815 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:href" ), url );
2816 element.appendChild( onlineResourceElem );
2818 QDomElement formatElem = doc.createElement( QStringLiteral(
"se:Format" ) );
2819 formatElem.appendChild( doc.createTextNode( format ) );
2820 element.appendChild( formatElem );
2827 QDomElement onlineResourceElem = element.firstChildElement( QStringLiteral(
"OnlineResource" ) );
2828 if ( onlineResourceElem.isNull() )
2831 path = onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) );
2833 QDomElement formatElem = element.firstChildElement( QStringLiteral(
"Format" ) );
2834 if ( formatElem.isNull() )
2837 format = formatElem.firstChild().nodeValue();
2844 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:SvgParameter" ) );
2845 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
2846 nodeElem.appendChild( doc.createTextNode( value ) );
2855 QDomElement paramElem = element.firstChildElement();
2856 while ( !paramElem.isNull() )
2858 if ( paramElem.localName() == QLatin1String(
"SvgParameter" ) || paramElem.localName() == QLatin1String(
"CssParameter" ) )
2860 QString name = paramElem.attribute( QStringLiteral(
"name" ) );
2861 if ( paramElem.firstChild().nodeType() == QDomNode::TextNode )
2863 value = paramElem.firstChild().nodeValue();
2867 if ( paramElem.firstChild().nodeType() == QDomNode::ElementNode &&
2868 paramElem.firstChild().localName() == QLatin1String(
"Literal" ) )
2870 QgsDebugMsg( paramElem.firstChild().localName() );
2871 value = paramElem.firstChild().firstChild().nodeValue();
2875 QgsDebugMsg( QStringLiteral(
"unexpected child of %1" ).arg( paramElem.localName() ) );
2879 if ( !name.isEmpty() && !value.isEmpty() )
2880 params[ name ] = value;
2883 paramElem = paramElem.nextSiblingElement();
2891 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:VendorOption" ) );
2892 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
2893 nodeElem.appendChild( doc.createTextNode( value ) );
2901 QDomElement paramElem = element.firstChildElement( QStringLiteral(
"VendorOption" ) );
2902 while ( !paramElem.isNull() )
2904 QString name = paramElem.attribute( QStringLiteral(
"name" ) );
2905 QString value = paramElem.firstChild().nodeValue();
2907 if ( !name.isEmpty() && !value.isEmpty() )
2908 params[ name ] = value;
2910 paramElem = paramElem.nextSiblingElement( QStringLiteral(
"VendorOption" ) );
2920 QDomElement e = element.firstChildElement();
2921 while ( !e.isNull() )
2923 if ( e.tagName() == QLatin1String(
"prop" ) )
2925 QString propKey = e.attribute( QStringLiteral(
"k" ) );
2926 QString propValue = e.attribute( QStringLiteral(
"v" ) );
2927 props[propKey] = propValue;
2929 e = e.nextSiblingElement();
2937 for ( QgsStringMap::iterator it = props.begin(); it != props.end(); ++it )
2939 QDomElement propEl = doc.createElement( QStringLiteral(
"prop" ) );
2940 propEl.setAttribute( QStringLiteral(
"k" ), it.key() );
2941 propEl.setAttribute( QStringLiteral(
"v" ), it.value() );
2942 element.appendChild( propEl );
2951 QDomElement e = element.firstChildElement();
2953 while ( !e.isNull() )
2955 if ( e.tagName() == QLatin1String(
"symbol" ) )
2959 symbols.insert( e.attribute( QStringLiteral(
"name" ) ), symbol );
2965 e = e.nextSiblingElement();
2972 QStringList subsymbols;
2974 for ( QMap<QString, QgsSymbol *>::iterator it = symbols.begin(); it != symbols.end(); ++it )
2976 if ( it.key()[0] !=
'@' )
2980 subsymbols.append( it.key() );
2982 QStringList parts = it.key().split(
'@' );
2983 if ( parts.count() < 3 )
2985 QgsDebugMsg(
"found subsymbol with invalid name: " + it.key() );
2989 QString symname = parts[1];
2990 int symlayer = parts[2].toInt();
2992 if ( !symbols.contains( symname ) )
2994 QgsDebugMsg(
"subsymbol references invalid symbol: " + symname );
3002 QgsDebugMsg(
"subsymbol references invalid symbol layer: " + QString::number( symlayer ) );
3011 QgsDebugMsg(
"symbol layer refused subsymbol: " + it.key() );
3018 for (
int i = 0; i < subsymbols.count(); i++ )
3019 symbols.take( subsymbols[i] );
3026 QDomElement symbolsElem = doc.createElement( tagName );
3029 for ( QMap<QString, QgsSymbol *>::iterator its = symbols.begin(); its != symbols.end(); ++its )
3031 QDomElement symEl =
saveSymbol( its.key(), its.value(), doc, context );
3032 symbolsElem.appendChild( symEl );
3040 qDeleteAll( symbols );
3049 std::unique_ptr< QMimeData >mimeData(
new QMimeData );
3051 QDomDocument symbolDoc;
3053 symbolDoc.appendChild( symbolElem );
3054 mimeData->setText( symbolDoc.toString() );
3057 mimeData->setColorData( symbol->
color() );
3059 return mimeData.release();
3067 QString text = data->text();
3068 if ( !text.isEmpty() )
3073 if ( doc.setContent( text ) )
3075 elem = doc.documentElement();
3077 if ( elem.nodeName() != QLatin1String(
"symbol" ) )
3078 elem = elem.firstChildElement( QStringLiteral(
"symbol" ) );
3089 QString rampType = element.attribute( QStringLiteral(
"type" ) );
3106 QgsDebugMsg(
"unknown colorramp type " + rampType );
3114 QDomElement rampEl = doc.createElement( QStringLiteral(
"colorramp" ) );
3115 rampEl.setAttribute( QStringLiteral(
"type" ), ramp->
type() );
3116 rampEl.setAttribute( QStringLiteral(
"name" ), name );
3124 QVariantMap rampMap;
3126 rampMap.insert( QStringLiteral(
"type" ), ramp->
type() );
3127 rampMap.insert( QStringLiteral(
"name" ), name );
3131 QVariantMap propertyMap;
3132 for (
auto property = properties.constBegin(); property != properties.constEnd(); ++property )
3134 propertyMap.insert( property.key(), property.value() );
3137 rampMap.insert( QStringLiteral(
"properties" ), propertyMap );
3143 QVariantMap rampMap = value.toMap();
3145 QString rampType = rampMap.
value( QStringLiteral(
"type" ) ).toString();
3148 QVariantMap propertyMap = rampMap.value( QStringLiteral(
"properties" ) ).toMap();
3151 for (
auto property = propertyMap.constBegin(); property != propertyMap.constEnd(); ++property )
3153 props.insert( property.key(), property.value().toString() );
3168 QgsDebugMsg(
"unknown colorramp type " + rampType );
3175 if ( !color.isValid() )
3182 return color.name();
3187 QList<QColor> colors;
3190 QStringList components = colorStr.simplified().split( QRegExp(
"(,|\\s)" ) );
3191 QStringList::iterator it = components.begin();
3192 for ( ; it != components.end(); ++it )
3195 if ( result.isValid() )
3200 if ( colors.length() > 0 )
3206 components = colorStr.split( QRegExp(
"(,|\n)" ) );
3207 it = components.begin();
3208 for ( ; it != components.end(); ++it )
3211 if ( result.isValid() )
3216 if ( colors.length() > 0 )
3222 components = colorStr.simplified().split( QString(
' ' ) );
3223 it = components.begin();
3224 for ( ; it != components.end(); ++it )
3227 if ( result.isValid() )
3232 if ( colors.length() > 0 )
3238 components = colorStr.split(
'\n' );
3239 it = components.begin();
3240 for ( ; it != components.end(); ++it )
3243 if ( result.isValid() )
3256 QMimeData *mimeData =
new QMimeData;
3257 mimeData->setColorData( QVariant( color ) );
3258 mimeData->setText( color.name() );
3265 if ( mimeData->hasColor() )
3267 QColor mimeColor = mimeData->colorData().value<QColor>();
3268 if ( mimeColor.isValid() )
3276 if ( mimeData->hasText() )
3280 if ( textColor.isValid() )
3295 if ( data->hasFormat( QStringLiteral(
"text/xml" ) ) )
3298 QByteArray encodedData = data->data( QStringLiteral(
"text/xml" ) );
3299 QDomDocument xmlDoc;
3300 xmlDoc.setContent( encodedData );
3302 QDomElement dragDataElem = xmlDoc.documentElement();
3303 if ( dragDataElem.tagName() == QLatin1String(
"ColorSchemeModelDragData" ) )
3305 QDomNodeList nodeList = dragDataElem.childNodes();
3306 int nChildNodes = nodeList.size();
3307 QDomElement currentElem;
3309 for (
int i = 0; i < nChildNodes; ++i )
3311 currentElem = nodeList.at( i ).toElement();
3312 if ( currentElem.isNull() )
3317 QPair< QColor, QString> namedColor;
3319 namedColor.second = currentElem.attribute( QStringLiteral(
"label" ), QString() );
3321 mimeColors << namedColor;
3326 if ( mimeColors.length() == 0 && data->hasFormat( QStringLiteral(
"application/x-colorobject-list" ) ) )
3329 QByteArray encodedData = data->data( QStringLiteral(
"application/x-colorobject-list" ) );
3330 QDomDocument xmlDoc;
3331 xmlDoc.setContent( encodedData );
3333 QDomNodeList colorsNodes = xmlDoc.elementsByTagName( QStringLiteral(
"colors" ) );
3334 if ( colorsNodes.length() > 0 )
3336 QDomElement colorsElem = colorsNodes.at( 0 ).toElement();
3337 QDomNodeList colorNodeList = colorsElem.childNodes();
3338 int nChildNodes = colorNodeList.size();
3339 QDomElement currentElem;
3341 for (
int i = 0; i < nChildNodes; ++i )
3344 currentElem = colorNodeList.at( i ).toElement();
3345 if ( currentElem.isNull() )
3350 QDomNodeList colorNodes = currentElem.elementsByTagName( QStringLiteral(
"color" ) );
3351 QDomNodeList nameNodes = currentElem.elementsByTagName( QStringLiteral(
"name" ) );
3353 if ( colorNodes.length() > 0 )
3355 QDomElement colorElem = colorNodes.at( 0 ).toElement();
3357 QStringList colorParts = colorElem.text().simplified().split(
' ' );
3358 if ( colorParts.length() < 3 )
3363 int red = colorParts.at( 0 ).toDouble() * 255;
3364 int green = colorParts.at( 1 ).toDouble() * 255;
3365 int blue = colorParts.at( 2 ).toDouble() * 255;
3366 QPair< QColor, QString> namedColor;
3367 namedColor.first = QColor( red, green, blue );
3368 if ( nameNodes.length() > 0 )
3370 QDomElement nameElem = nameNodes.at( 0 ).toElement();
3371 namedColor.second = nameElem.text();
3373 mimeColors << namedColor;
3379 if ( mimeColors.length() == 0 && data->hasText() )
3383 QList< QColor >::iterator it = parsedColors.begin();
3384 for ( ; it != parsedColors.end(); ++it )
3386 mimeColors << qMakePair( *it, QString() );
3390 if ( mimeColors.length() == 0 && data->hasColor() )
3393 QColor mimeColor = data->colorData().value<QColor>();
3394 if ( mimeColor.isValid() )
3396 mimeColors << qMakePair( mimeColor, QString() );
3406 QMimeData *mimeData =
new QMimeData();
3407 QDomDocument xmlDoc;
3408 QDomElement xmlRootElement = xmlDoc.createElement( QStringLiteral(
"ColorSchemeModelDragData" ) );
3409 xmlDoc.appendChild( xmlRootElement );
3411 QgsNamedColorList::const_iterator colorIt = colorList.constBegin();
3412 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3414 QDomElement namedColor = xmlDoc.createElement( QStringLiteral(
"NamedColor" ) );
3416 namedColor.setAttribute( QStringLiteral(
"label" ), ( *colorIt ).second );
3417 xmlRootElement.appendChild( namedColor );
3419 mimeData->setData( QStringLiteral(
"text/xml" ), xmlDoc.toByteArray() );
3427 colorIt = colorList.constBegin();
3428 QStringList colorListString;
3429 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3431 colorListString << ( *colorIt ).first.name();
3433 mimeData->setText( colorListString.join( QLatin1Char(
'\n' ) ) );
3436 if ( colorList.length() > 0 )
3438 mimeData->setColorData( QVariant( colorList.at( 0 ).first ) );
3446 if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3451 QTextStream stream( &file );
3452 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3453 stream <<
"GIMP Palette" << endl;
3455 stream <<
"GIMP Palette" << Qt::endl;
3457 if ( paletteName.isEmpty() )
3459 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3460 stream <<
"Name: QGIS Palette" << endl;
3462 stream <<
"Name: QGIS Palette" << Qt::endl;
3467 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3468 stream <<
"Name: " << paletteName << endl;
3470 stream <<
"Name: " << paletteName << Qt::endl;
3473 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3474 stream <<
"Columns: 4" << endl;
3475 stream <<
'#' << endl;
3477 stream <<
"Columns: 4" << Qt::endl;
3478 stream <<
'#' << Qt::endl;
3481 for ( QgsNamedColorList::ConstIterator colorIt = colors.constBegin(); colorIt != colors.constEnd(); ++colorIt )
3483 QColor color = ( *colorIt ).first;
3484 if ( !color.isValid() )
3488 stream << QStringLiteral(
"%1 %2 %3" ).arg( color.red(), 3 ).arg( color.green(), 3 ).arg( color.blue(), 3 );
3489 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3490 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << endl;
3492 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << Qt::endl;
3504 if ( !file.open( QIODevice::ReadOnly ) )
3507 return importedColors;
3510 QTextStream in( &file );
3512 QString line = in.readLine();
3513 if ( !line.startsWith( QLatin1String(
"GIMP Palette" ) ) )
3516 return importedColors;
3520 while ( !in.atEnd() && !line.startsWith( QLatin1String(
"Name:" ) ) && !line.startsWith(
'#' ) )
3522 line = in.readLine();
3524 if ( line.startsWith( QLatin1String(
"Name:" ) ) )
3526 QRegExp nameRx(
"Name:\\s*(\\S.*)$" );
3527 if ( nameRx.indexIn( line ) != -1 )
3529 name = nameRx.cap( 1 );
3534 while ( !in.atEnd() && !line.startsWith(
'#' ) )
3536 line = in.readLine();
3541 return importedColors;
3545 QRegExp rx(
"^\\s*(\\d+)\\s+(\\d+)\\s+(\\d+)(\\s.*)?$" );
3546 while ( !in.atEnd() )
3548 line = in.readLine();
3549 if ( rx.indexIn( line ) == -1 )
3553 int red = rx.cap( 1 ).toInt();
3554 int green = rx.cap( 2 ).toInt();
3555 int blue = rx.cap( 3 ).toInt();
3556 QColor color = QColor( red, green, blue );
3557 if ( !color.isValid() )
3564 if ( rx.captureCount() > 3 )
3566 label = rx.cap( 4 ).simplified();
3573 importedColors << qMakePair( color, label );
3578 return importedColors;
3591 QRegExp hexColorAlphaRx(
"^\\s*#?([0-9a-fA-F]{6})([0-9a-fA-F]{2})\\s*$" );
3592 int hexColorIndex = hexColorAlphaRx.indexIn( colorStr );
3595 if ( hexColorIndex == -1 && QColor::isValidColor( colorStr ) )
3598 parsedColor.setNamedColor( colorStr );
3599 if ( parsedColor.isValid() )
3601 containsAlpha =
false;
3607 if ( hexColorIndex > -1 )
3609 QString hexColor = hexColorAlphaRx.cap( 1 );
3610 parsedColor.setNamedColor( QStringLiteral(
"#" ) + hexColor );
3612 int alphaHex = hexColorAlphaRx.cap( 2 ).toInt( &alphaOk, 16 );
3614 if ( parsedColor.isValid() && alphaOk )
3616 parsedColor.setAlpha( alphaHex );
3617 containsAlpha =
true;
3625 QRegExp hexColorRx2(
"^\\s*(?:[0-9a-fA-F]{3}){1,2}\\s*$" );
3626 if ( hexColorRx2.indexIn( colorStr ) != -1 )
3629 parsedColor.setNamedColor( QStringLiteral(
"#" ) + colorStr );
3630 if ( parsedColor.isValid() )
3632 containsAlpha =
false;
3639 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*$" );
3640 if ( rgbFormatRx.indexIn( colorStr ) != -1 )
3642 int r = rgbFormatRx.cap( 1 ).toInt();
3643 int g = rgbFormatRx.cap( 2 ).toInt();
3644 int b = rgbFormatRx.cap( 3 ).toInt();
3645 parsedColor.setRgb( r, g, b );
3646 if ( parsedColor.isValid() )
3648 containsAlpha =
false;
3654 const QRegularExpression hslFormatRx(
"^\\s*hsl\\(?\\s*(\\d+)\\s*,\\s*(\\d+)\\s*%\\s*,\\s*(\\d+)\\s*%\\s*\\)?\\s*;?\\s*$" );
3655 QRegularExpressionMatch match = hslFormatRx.match( colorStr );
3656 if ( match.hasMatch() )
3658 int h = match.captured( 1 ).toInt();
3659 int s = match.captured( 2 ).toInt();
3660 int l = match.captured( 3 ).toInt();
3661 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0 );
3662 if ( parsedColor.isValid() )
3664 containsAlpha =
false;
3670 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*$" );
3671 if ( rgbPercentFormatRx.indexIn( colorStr ) != -1 )
3673 int r = std::round( rgbPercentFormatRx.cap( 1 ).toDouble() * 2.55 );
3674 int g = std::round( rgbPercentFormatRx.cap( 2 ).toDouble() * 2.55 );
3675 int b = std::round( rgbPercentFormatRx.cap( 3 ).toDouble() * 2.55 );
3676 parsedColor.setRgb( r, g, b );
3677 if ( parsedColor.isValid() )
3679 containsAlpha =
false;
3685 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*$" );
3686 if ( rgbaFormatRx.indexIn( colorStr ) != -1 )
3688 int r = rgbaFormatRx.cap( 1 ).toInt();
3689 int g = rgbaFormatRx.cap( 2 ).toInt();
3690 int b = rgbaFormatRx.cap( 3 ).toInt();
3691 int a = std::round( rgbaFormatRx.cap( 4 ).toDouble() * 255.0 );
3692 parsedColor.setRgb( r, g, b, a );
3693 if ( parsedColor.isValid() )
3695 containsAlpha =
true;
3701 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*$" );
3702 if ( rgbaPercentFormatRx.indexIn( colorStr ) != -1 )
3704 int r = std::round( rgbaPercentFormatRx.cap( 1 ).toDouble() * 2.55 );
3705 int g = std::round( rgbaPercentFormatRx.cap( 2 ).toDouble() * 2.55 );
3706 int b = std::round( rgbaPercentFormatRx.cap( 3 ).toDouble() * 2.55 );
3707 int a = std::round( rgbaPercentFormatRx.cap( 4 ).toDouble() * 255.0 );
3708 parsedColor.setRgb( r, g, b, a );
3709 if ( parsedColor.isValid() )
3711 containsAlpha =
true;
3717 const QRegularExpression hslaPercentFormatRx(
"^\\s*hsla\\(?\\s*(\\d+)\\s*,\\s*(\\d+)\\s*%\\s*,\\s*(\\d+)\\s*%\\s*,\\s*([\\d\\.]+)\\s*\\)?\\s*;?\\s*$" );
3718 match = hslaPercentFormatRx.match( colorStr );
3719 if ( match.hasMatch() )
3721 int h = match.captured( 1 ).toInt();
3722 int s = match.captured( 2 ).toInt();
3723 int l = match.captured( 3 ).toInt();
3724 int a = std::round( match.captured( 4 ).toDouble() * 255.0 );
3725 parsedColor.setHsl( h, s / 100.0 * 255.0, l / 100.0 * 255.0, a );
3726 if ( parsedColor.isValid() )
3728 containsAlpha =
true;
3745 QImage::Format format = image->format();
3746 if ( format != QImage::Format_ARGB32_Premultiplied && format != QImage::Format_ARGB32 )
3748 QgsDebugMsg( QStringLiteral(
"no alpha channel." ) );
3753 for (
int heightIndex = 0; heightIndex < image->height(); ++heightIndex )
3755 QRgb *scanLine =
reinterpret_cast< QRgb *
>( image->scanLine( heightIndex ) );
3756 for (
int widthIndex = 0; widthIndex < image->width(); ++widthIndex )
3758 myRgb = scanLine[widthIndex];
3759 if ( format == QImage::Format_ARGB32_Premultiplied )
3760 scanLine[widthIndex] = qRgba( opacity * qRed( myRgb ), opacity * qGreen( myRgb ), opacity * qBlue( myRgb ), opacity * qAlpha( myRgb ) );
3762 scanLine[widthIndex] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), opacity * qAlpha( myRgb ) );
3770 int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
3771 int alpha = ( radius < 1 ) ? 16 : ( radius > 17 ) ? 1 : tab[radius - 1];
3773 if ( image.format() != QImage::Format_ARGB32_Premultiplied
3774 && image.format() != QImage::Format_RGB32 )
3776 image = image.convertToFormat( QImage::Format_ARGB32_Premultiplied );
3779 int r1 = rect.top();
3780 int r2 = rect.bottom();
3781 int c1 = rect.left();
3782 int c2 = rect.right();
3784 int bpl = image.bytesPerLine();
3792 i1 = i2 = ( QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3 );
3794 for (
int col = c1; col <= c2; col++ )
3796 p = image.scanLine( r1 ) + col * 4;
3797 for (
int i = i1; i <= i2; i++ )
3798 rgba[i] = p[i] << 4;
3801 for (
int j = r1; j < r2; j++, p += bpl )
3802 for (
int i = i1; i <= i2; i++ )
3803 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
3806 for (
int row = r1; row <= r2; row++ )
3808 p = image.scanLine( row ) + c1 * 4;
3809 for (
int i = i1; i <= i2; i++ )
3810 rgba[i] = p[i] << 4;
3813 for (
int j = c1; j < c2; j++, p += 4 )
3814 for (
int i = i1; i <= i2; i++ )
3815 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
3818 for (
int col = c1; col <= c2; col++ )
3820 p = image.scanLine( r2 ) + col * 4;
3821 for (
int i = i1; i <= i2; i++ )
3822 rgba[i] = p[i] << 4;
3825 for (
int j = r1; j < r2; j++, p -= bpl )
3826 for (
int i = i1; i <= i2; i++ )
3827 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
3830 for (
int row = r1; row <= r2; row++ )
3832 p = image.scanLine( row ) + c2 * 4;
3833 for (
int i = i1; i <= i2; i++ )
3834 rgba[i] = p[i] << 4;
3837 for (
int j = c1; j < c2; j++, p -= 4 )
3838 for (
int i = i1; i <= i2; i++ )
3839 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
3845 if ( alpha != 255 && alpha > 0 )
3849 double alphaFactor = alpha / 255.;
3850 int r = 0, g = 0, b = 0;
3851 rgb.getRgb( &r, &g, &b );
3856 rgb.setRgb( r, g, b, alpha );
3858 else if ( alpha == 0 )
3860 rgb.setRgb( 0, 0, 0, 0 );
3866 if ( order == Qt::AscendingOrder )
3880 double dx = directionPoint.x() - startPoint.x();
3881 double dy = directionPoint.y() - startPoint.y();
3882 double length = std::sqrt( dx * dx + dy * dy );
3883 double scaleFactor = distance / length;
3884 return QPointF( startPoint.x() + dx * scaleFactor, startPoint.y() + dy * scaleFactor );
3894 for (
int i = 0; i < svgPaths.size(); i++ )
3896 QDir dir( svgPaths[i] );
3897 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
3898 for (
const QString &item : svgSubPaths )
3900 svgPaths.insert( i + 1, dir.path() +
'/' + item );
3903 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
3904 for (
const QString &item : svgFiles )
3907 list.append( dir.path() +
'/' + item );
3919 QStringList svgPaths;
3920 svgPaths.append( directory );
3922 for (
int i = 0; i < svgPaths.size(); i++ )
3924 QDir dir( svgPaths[i] );
3925 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
3926 for (
const QString &item : svgSubPaths )
3928 svgPaths.insert( i + 1, dir.path() +
'/' + item );
3931 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
3932 for (
const QString &item : svgFiles )
3934 list.append( dir.path() +
'/' + item );
3946 if ( n.startsWith( QLatin1String(
"base64:" ) ) )
3950 if ( QFileInfo::exists( n ) )
3951 return QFileInfo( n ).canonicalFilePath();
3955 if ( name.contains( QLatin1String(
"://" ) ) )
3958 if ( url.isValid() && !url.scheme().isEmpty() )
3960 if ( url.scheme().compare( QLatin1String(
"file" ), Qt::CaseInsensitive ) == 0 )
3963 name = url.toLocalFile();
3964 if ( QFile( name ).exists() )
3966 return QFileInfo( name ).canonicalFilePath();
3980 for (
int i = 0; i < svgPaths.size(); i++ )
3982 QString svgPath = svgPaths[i];
3983 if ( svgPath.endsWith( QChar(
'/' ) ) )
3994 QString myLocalPath = svgPath + QDir::separator() + name;
3997 if ( QFile( myLocalPath ).exists() )
4000 return QFileInfo( myLocalPath ).canonicalFilePath();
4004 return pathResolver.
readPath( name );
4012 if ( p.startsWith( QLatin1String(
"base64:" ) ) )
4015 if ( !QFileInfo::exists( p ) )
4018 QString path = QFileInfo( p ).canonicalFilePath();
4022 bool isInSvgPaths =
false;
4023 for (
int i = 0; i < svgPaths.size(); i++ )
4025 QString dir = QFileInfo( svgPaths[i] ).canonicalFilePath();
4027 if ( !dir.isEmpty() && path.startsWith( dir ) )
4029 path = path.mid( dir.size() + 1 );
4030 isInSvgPaths =
true;
4045 double cx = 0, cy = 0;
4046 double area, sum = 0;
4047 for (
int i = points.count() - 1, j = 0; j < points.count(); i = j++ )
4049 const QPointF &p1 = points[i];
4050 const QPointF &p2 = points[j];
4051 area = p1.x() * p2.y() - p1.y() * p2.x();
4053 cx += ( p1.x() + p2.x() ) * area;
4054 cy += ( p1.y() + p2.y() ) * area;
4061 if ( points.count() >= 2 )
4062 return QPointF( ( points[0].x() + points[1].x() ) / 2, ( points[0].y() + points[1].y() ) / 2 );
4063 else if ( points.count() == 1 )
4071 return QPointF( cx, cy );
4078 if ( ( rings && rings->count() > 0 ) || !
pointInPolygon( points, centroid ) )
4080 unsigned int i, pointCount = points.count();
4082 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( points[i].x(), points[i].y() );
4088 for (
auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
4090 pointCount = ( *ringIt ).count();
4092 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( ( *ringIt )[i].x(), ( *ringIt )[i].y() );
4098 if ( !pointOnSurfaceGeom.
isNull() )
4101 centroid.
setX( point.
x() );
4102 centroid.setY( point.
y() );
4107 return QPointF( centroid.x(), centroid.y() );
4112 bool inside =
false;
4114 double x = point.x();
4115 double y = point.y();
4117 for (
int i = 0, j = points.count() - 1; i < points.count(); i++ )
4119 const QPointF &p1 = points[i];
4120 const QPointF &p2 = points[j];
4125 if ( ( p1.y() < y && p2.y() >= y ) || ( p2.y() < y && p1.y() >= y ) )
4127 if ( p1.x() + ( y - p1.y() ) / ( p2.y() - p1.y() ) * ( p2.x() - p1.x() ) <= x )
4138 if ( polyline.size() < 2 )
4141 double totalLength = 0;
4142 auto it = polyline.begin();
4144 std::vector< double > segmentLengths( polyline.size() - 1 );
4145 auto segmentLengthIt = segmentLengths.begin();
4146 for ( ; it != polyline.end(); ++it )
4149 *segmentLengthIt = std::sqrt( std::pow( p1.x() - p2.x(), 2.0 ) + std::pow( p1.y() - p2.y(), 2.0 ) );
4150 totalLength += *segmentLengthIt;
4156 if ( startOffset >= 0 && totalLength <= startOffset )
4158 if ( endOffset < 0 && totalLength <= -endOffset )
4161 const double startDistance = startOffset < 0 ? totalLength + startOffset : startOffset;
4162 const double endDistance = endOffset <= 0 ? totalLength + endOffset : endOffset;
4163 QPolygonF substringPoints;
4164 substringPoints.reserve( polyline.size() );
4166 it = polyline.begin();
4167 segmentLengthIt = segmentLengths.begin();
4170 bool foundStart =
false;
4171 if (
qgsDoubleNear( startDistance, 0.0 ) || startDistance < 0 )
4173 substringPoints << p1;
4177 double distanceTraversed = 0;
4178 for ( ; it != polyline.end(); ++it )
4181 if ( distanceTraversed < startDistance && distanceTraversed + *segmentLengthIt > startDistance )
4184 const double distanceToStart = startDistance - distanceTraversed;
4185 double startX, startY;
4187 substringPoints << QPointF( startX, startY );
4190 if ( foundStart && ( distanceTraversed + *segmentLengthIt > endDistance ) )
4193 const double distanceToEnd = endDistance - distanceTraversed;
4196 if ( substringPoints.last() != QPointF( endX, endY ) )
4197 substringPoints << QPointF( endX, endY );
4199 else if ( foundStart )
4201 if ( substringPoints.last() != QPointF( p2.x(), p2.y() ) )
4202 substringPoints << QPointF( p2.x(), p2.y() );
4205 distanceTraversed += *segmentLengthIt;
4206 if ( distanceTraversed > endDistance )
4213 if ( ( substringPoints.size() < 2 ) || ( substringPoints.size() == 2 && substringPoints.at( 0 ) == substringPoints.at( 1 ) ) )
4216 return substringPoints;
4221 double vertexAngle = M_PI - ( std::atan2( p3.y() - p2.y(), p3.x() - p2.x() ) - std::atan2( p2.y() - p1.y(), p2.x() - p1.x() ) );
4225 return vertexAngle < M_PI * 135.0 / 180.0 || vertexAngle > M_PI * 225.0 / 180.0;
4230 target.reserve( target.size() + line.size() );
4231 for (
const QPointF &pt : line )
4233 if ( !target.empty() && target.last() == pt )
4242 if ( fieldOrExpression.isEmpty() )
4277 QList<double> breaks;
4280 breaks.append( maximum );
4284 int minimumCount =
static_cast< int >( classes ) / 3;
4285 double shrink = 0.75;
4286 double highBias = 1.5;
4287 double adjustBias = 0.5 + 1.5 * highBias;
4288 int divisions = classes;
4289 double h = highBias;
4292 double dx = maximum - minimum;
4302 cell = std::max( std::fabs( minimum ), std::fabs( maximum ) );
4303 if ( adjustBias >= 1.5 * h + 0.5 )
4305 U = 1 + ( 1.0 / ( 1 + h ) );
4309 U = 1 + ( 1.5 / ( 1 + adjustBias ) );
4311 small = dx < ( cell * U * std::max( 1, divisions ) * 1e-07 * 3.0 );
4318 cell = 9 + cell / 10;
4319 cell = cell * shrink;
4321 if ( minimumCount > 1 )
4323 cell = cell / minimumCount;
4329 if ( divisions > 1 )
4331 cell = cell / divisions;
4334 if ( cell < 20 * 1e-07 )
4339 double base = std::pow( 10.0, std::floor( std::log10( cell ) ) );
4341 if ( ( 2 * base ) - cell < h * ( cell - unit ) )
4344 if ( ( 5 * base ) - cell < adjustBias * ( cell - unit ) )
4347 if ( ( 10.0 * base ) - cell < h * ( cell - unit ) )
4354 int start = std::floor( minimum / unit + 1e-07 );
4355 int end = std::ceil( maximum / unit - 1e-07 );
4358 while ( start * unit > minimum + ( 1e-07 * unit ) )
4362 while ( end * unit < maximum - ( 1e-07 * unit ) )
4366 QgsDebugMsg( QStringLiteral(
"pretty classes: %1" ).arg( end ) );
4370 int k = std::floor( 0.5 + end - start );
4371 if ( k < minimumCount )
4373 k = minimumCount - k;
4377 start = start - k / 2 + k % 2;
4381 start = start - k / 2;
4382 end = end + k / 2 + k % 2;
4385 double minimumBreak = start * unit;
4387 int count = end - start;
4389 breaks.reserve( count );
4390 for (
int i = 1; i < count + 1; i++ )
4392 breaks.append( minimumBreak + i * unit );
4395 if ( breaks.isEmpty() )
4398 if ( breaks.first() < minimum )
4400 breaks[0] = minimum;
4402 if ( breaks.last() > maximum )
4404 breaks[breaks.count() - 1] = maximum;
4409 if ( minimum < 0.0 && maximum > 0.0 )
4411 QList<double> breaksMinusZero;
4412 for (
int i = 0; i < breaks.count(); i++ )
4414 breaksMinusZero.append( breaks[i] - 0.0 );
4417 for (
int i = 1; i < breaks.count(); i++ )
4419 if ( std::abs( breaksMinusZero[i] ) < std::abs( breaksMinusZero[i - 1] ) )
4422 breaks[posOfMin] = 0.0;
4431 bool roundToUnit =
false;
4434 if ( props.contains( QStringLiteral(
"uomScale" ) ) )
4437 scale = props.value( QStringLiteral(
"uomScale" ) ).toDouble( &ok );
4446 if ( props.value( QStringLiteral(
"uom" ) ) == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
4471 scale = 1 / 0.28 * 25.4;
4495 double rescaled = size * scale;
4500 rescaled = std::round( rescaled );
4507 double x =
rescaleUom( point.x(), unit, props );
4508 double y =
rescaleUom( point.y(), unit, props );
4509 return QPointF( x, y );
4514 QVector<qreal> result;
4515 QVector<qreal>::const_iterator it = array.constBegin();
4516 for ( ; it != array.constEnd(); ++it )
4518 result.append(
rescaleUom( *it, unit, props ) );
4525 if ( !props.value( QStringLiteral(
"scaleMinDenom" ), QString() ).isEmpty() )
4527 QDomElement scaleMinDenomElem = doc.createElement( QStringLiteral(
"se:MinScaleDenominator" ) );
4528 scaleMinDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMinDenom" ) ).toDouble() ) ) );
4529 ruleElem.appendChild( scaleMinDenomElem );
4532 if ( !props.value( QStringLiteral(
"scaleMaxDenom" ), QString() ).isEmpty() )
4534 QDomElement scaleMaxDenomElem = doc.createElement( QStringLiteral(
"se:MaxScaleDenominator" ) );
4535 scaleMaxDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMaxDenom" ) ).toDouble() ) ) );
4536 ruleElem.appendChild( scaleMaxDenomElem );
4545 double parentScaleMinDenom = props.value( QStringLiteral(
"scaleMinDenom" ), QStringLiteral(
"0" ) ).toDouble( &ok );
4546 if ( !ok || parentScaleMinDenom <= 0 )
4547 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( mScaleMinDenom );
4549 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( std::max( parentScaleMinDenom, mScaleMinDenom ) );
4555 double parentScaleMaxDenom = props.value( QStringLiteral(
"scaleMaxDenom" ), QStringLiteral(
"0" ) ).toDouble( &ok );
4556 if ( !ok || parentScaleMaxDenom <= 0 )
4557 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( mScaleMaxDenom );
4559 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( std::min( parentScaleMaxDenom, mScaleMaxDenom ) );
4567 if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
4569 scale = 1.0 / 0.00028;
4571 else if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
4573 scale = 304.8 / 0.28;
4580 return size * scale;
4589 : mSymbolLayerIds( layerIds )
4602 void visitSymbol(
const QgsSymbol *symbol,
const QString &identifier, QVector<int> rootPath )
4606 QVector<int> indexPath = rootPath;
4607 indexPath.append( idx );
4609 if ( mSymbolLayerIds.contains(
QgsSymbolLayerId( mCurrentRuleKey + identifier, indexPath ) ) )
4611 mSymbolLayers.insert( sl );
4616 visitSymbol( subSymbol, identifier, indexPath );
4625 if ( symbolEntity->symbol() )
4627 visitSymbol( symbolEntity->symbol(), leaf.
identifier, {} );
4633 QString mCurrentRuleKey;
4634 const QSet<QgsSymbolLayerId> &mSymbolLayerIds;
4635 QSet<const QgsSymbolLayer *> mSymbolLayers;
4639 renderer->
accept( &visitor );
4640 return visitor.mSymbolLayers;
4645 if ( !s || !context )
4655 size = markerSymbol->
size( *context );
4657 else if ( lineSymbol )
4659 size = lineSymbol->
width( *context );
4668 if ( minSize > 0 && size < minSize )
4672 else if ( maxSize > 0 && size > maxSize )
4690 else if ( lineSymbol )