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 );
775 painter.setRenderHint( QPainter::Antialiasing );
784 size.setWidth( size.rwidth() - ( padding * 2 ) );
785 size.setHeight( size.rheight() - ( padding * 2 ) );
786 painter.translate( padding, padding );
796 std::unique_ptr<QgsSymbol> symbol_noDD( symbol->
clone( ) );
798 for (
const auto &layer : layers )
800 for (
int i = 0; i < layer->dataDefinedProperties().count(); ++i )
802 QgsProperty &prop = layer->dataDefinedProperties().property( i );
808 symbol_noDD->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape );
812 std::unique_ptr<QgsSymbol> symbolClone( symbol->
clone( ) );
813 symbolClone->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape );
827 maxBleed = layerMaxBleed > maxBleed ? layerMaxBleed : maxBleed;
837 painter.begin( &picture );
838 painter.setRenderHint( QPainter::Antialiasing );
843 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
844 layerClone->drawPreviewIcon( symbolContext, size );
851 QPixmap pixmap( size );
852 pixmap.fill( Qt::transparent );
854 painter.begin( &pixmap );
855 painter.setRenderHint( QPainter::Antialiasing );
864 std::unique_ptr< QgsSymbolLayer > layerClone( layer->
clone() );
865 layerClone->drawPreviewIcon( symbolContext, size );
867 return QIcon( pixmap );
877 QPixmap pixmap( size );
878 pixmap.fill( Qt::transparent );
881 painter.begin( &pixmap );
884 drawStippledBackground( &painter, QRect( padding, padding, size.width() - padding * 2, size.height() - padding * 2 ) );
888 for (
int i = 0; i < size.width(); i++ )
890 QPen pen( ramp->
color(
static_cast< double >( i ) / size.width() ) );
891 painter.setPen( pen );
892 painter.drawLine( i, 0 + padding, i, size.height() - 1 - padding );
901 uchar pixDataRGB[] = { 255, 255, 255, 255,
906 QImage img( pixDataRGB, 2, 2, 8, QImage::Format_ARGB32 );
908 int width = ( rect.width() < rect.height() ) ?
909 rect.width() / 2.5 : rect.height() / 2.5;
910 QPixmap pix = QPixmap::fromImage( img.scaled( width, width ) );
913 brush.setTexture( pix );
914 painter->fillRect( rect, brush );
919 qreal s = ( markerSize - 1 ) / 2.0;
924 p.setPen( QColor( 50, 100, 120, 200 ) );
925 p.setBrush( QColor( 200, 200, 210, 120 ) );
926 p.drawEllipse( x - s, y - s, s * 2, s * 2 );
929 p.setPen( QColor( 255, 0, 0 ) );
930 p.drawLine( x - s, y + s, x + s, y - s );
931 p.drawLine( x - s, y - s, x + s, y + s );
943 static QPolygonF makeOffsetGeometry(
const QgsPolylineXY &polyline )
945 int i, pointCount = polyline.count();
947 QPolygonF resultLine;
948 resultLine.resize( pointCount );
952 for ( i = 0; i < pointCount; ++i, tempPtr++ )
953 resultLine[i] = QPointF( tempPtr->
x(), tempPtr->
y() );
957 static QList<QPolygonF> makeOffsetGeometry(
const QgsPolygonXY &polygon )
959 QList<QPolygonF> resultGeom;
960 resultGeom.reserve( polygon.size() );
961 for (
int ring = 0; ring < polygon.size(); ++ring )
962 resultGeom.append( makeOffsetGeometry( polygon[ ring ] ) );
968 QList<QPolygonF> resultLine;
970 if ( polyline.count() < 2 )
972 resultLine.append( polyline );
976 unsigned int i, pointCount = polyline.count();
979 QPointF *tempPtr = polyline.data();
980 for ( i = 0; i < pointCount; ++i, tempPtr++ )
981 tempPolyline[i] =
QgsPointXY( tempPtr->rx(), tempPtr->ry() );
984 if ( !tempGeometry.
isNull() )
986 int quadSegments = 0;
987 double miterLimit = 2.0;
995 if ( !offsetGeom.
isNull() )
997 tempGeometry = offsetGeom;
1002 resultLine.append( makeOffsetGeometry( line ) );
1007 resultLine.append( makeOffsetGeometry( tempGeometry.
asPolygon() ) );
1013 resultLine.reserve( tempMPolyline.count() );
1014 for (
int part = 0; part < tempMPolyline.count(); ++part )
1016 resultLine.append( makeOffsetGeometry( tempMPolyline[ part ] ) );
1023 resultLine.reserve( tempMPolygon.count() );
1024 for (
int part = 0; part < tempMPolygon.count(); ++part )
1026 resultLine.append( makeOffsetGeometry( tempMPolygon[ part ] ) );
1034 resultLine.append( polyline );
1044 QDomNode layerNode = element.firstChild();
1046 while ( !layerNode.isNull() )
1048 QDomElement e = layerNode.toElement();
1051 if ( e.tagName() != QLatin1String(
"layer" ) )
1062 QDomElement s = e.firstChildElement( QStringLiteral(
"symbol" ) );
1069 QgsDebugMsg(
"symbol layer refused subsymbol: " + s.attribute(
"name" ) );
1072 layers.append( layer );
1076 layerNode = layerNode.nextSibling();
1079 if ( layers.isEmpty() )
1081 QgsDebugMsg( QStringLiteral(
"no layers for symbol" ) );
1085 QString symbolType = element.attribute( QStringLiteral(
"type" ) );
1088 if ( symbolType == QLatin1String(
"line" ) )
1090 else if ( symbolType == QLatin1String(
"fill" ) )
1092 else if ( symbolType == QLatin1String(
"marker" ) )
1096 QgsDebugMsg(
"unknown symbol type " + symbolType );
1100 if ( element.hasAttribute( QStringLiteral(
"outputUnit" ) ) )
1104 if ( element.hasAttribute( ( QStringLiteral(
"mapUnitScale" ) ) ) )
1107 double oldMin = element.attribute( QStringLiteral(
"mapUnitMinScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1108 mapUnitScale.
minScale = oldMin != 0 ? 1.0 / oldMin : 0;
1109 double oldMax = element.attribute( QStringLiteral(
"mapUnitMaxScale" ), QStringLiteral(
"0.0" ) ).toDouble();
1110 mapUnitScale.
maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
1113 symbol->
setOpacity( element.attribute( QStringLiteral(
"alpha" ), QStringLiteral(
"1.0" ) ).toDouble() );
1114 symbol->
setClipFeaturesToExtent( element.attribute( QStringLiteral(
"clip_to_extent" ), QStringLiteral(
"1" ) ).toInt() );
1115 symbol->
setForceRHR( element.attribute( QStringLiteral(
"force_rhr" ), QStringLiteral(
"0" ) ).toInt() );
1121 QString layerClass = element.attribute( QStringLiteral(
"class" ) );
1122 bool locked = element.attribute( QStringLiteral(
"locked" ) ).toInt();
1123 bool enabled = element.attribute( QStringLiteral(
"enabled" ), QStringLiteral(
"1" ) ).toInt();
1124 int pass = element.attribute( QStringLiteral(
"pass" ) ).toInt();
1141 QDomElement effectElem = element.firstChildElement( QStringLiteral(
"effect" ) );
1142 if ( !effectElem.isNull() )
1150 QDomElement ddProps = element.firstChildElement( QStringLiteral(
"data_defined_properties" ) );
1151 if ( !ddProps.isNull() )
1170 return QStringLiteral(
"line" );
1172 return QStringLiteral(
"marker" );
1174 return QStringLiteral(
"fill" );
1183 QDomElement symEl = doc.createElement( QStringLiteral(
"symbol" ) );
1184 symEl.setAttribute( QStringLiteral(
"type" ), _nameForSymbolType( symbol->
type() ) );
1185 symEl.setAttribute( QStringLiteral(
"name" ), name );
1186 symEl.setAttribute( QStringLiteral(
"alpha" ), QString::number( symbol->
opacity() ) );
1187 symEl.setAttribute( QStringLiteral(
"clip_to_extent" ), symbol->
clipFeaturesToExtent() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1188 symEl.setAttribute( QStringLiteral(
"force_rhr" ), symbol->
forceRHR() ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
1195 QDomElement layerEl = doc.createElement( QStringLiteral(
"layer" ) );
1196 layerEl.setAttribute( QStringLiteral(
"class" ), layer->
layerType() );
1197 layerEl.setAttribute( QStringLiteral(
"enabled" ), layer->
enabled() );
1198 layerEl.setAttribute( QStringLiteral(
"locked" ), layer->
isLocked() );
1199 layerEl.setAttribute( QStringLiteral(
"pass" ), layer->
renderingPass() );
1210 QDomElement ddProps = doc.createElement( QStringLiteral(
"data_defined_properties" ) );
1212 layerEl.appendChild( ddProps );
1216 QString subname = QStringLiteral(
"@%1@%2" ).arg( name ).arg( i );
1217 QDomElement subEl =
saveSymbol( subname, subSymbol, doc, context );
1218 layerEl.appendChild( subEl );
1220 symEl.appendChild( layerEl );
1228 QDomDocument doc( QStringLiteral(
"qgis-symbol-definition" ) );
1231 QTextStream stream( &props );
1232 symbolElem.save( stream, -1 );
1242 if ( element.isNull() )
1247 QString symbolizerName = element.localName();
1249 if ( symbolizerName == QLatin1String(
"PointSymbolizer" ) )
1252 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1253 if ( graphicElem.isNull() )
1255 QgsDebugMsg( QStringLiteral(
"Graphic element not found in PointSymbolizer" ) );
1291 if ( symbolizerName == QLatin1String(
"LineSymbolizer" ) )
1294 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1295 if ( strokeElem.isNull() )
1297 QgsDebugMsg( QStringLiteral(
"Stroke element not found in LineSymbolizer" ) );
1327 if ( symbolizerName == QLatin1String(
"PolygonSymbolizer" ) )
1330 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1331 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1332 if ( fillElem.isNull() && strokeElem.isNull() )
1334 QgsDebugMsg( QStringLiteral(
"neither Fill nor Stroke element not found in PolygonSymbolizer" ) );
1352 if ( l->
layerType() == QLatin1String(
"SimpleFill" ) || l->
layerType() == QLatin1String(
"SVGFill" ) )
1388 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1389 if ( fillElem.isNull() )
1391 QgsDebugMsg( QStringLiteral(
"Fill element not found" ) );
1411 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1412 if ( strokeElem.isNull() )
1414 QgsDebugMsg( QStringLiteral(
"Stroke element not found" ) );
1430 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1431 if ( graphicElem.isNull() )
1433 QgsDebugMsg( QStringLiteral(
"Graphic element not found" ) );
1453 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1454 if ( graphicElem.isNull() )
1457 QDomElement externalGraphicElem = graphicElem.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
1458 if ( externalGraphicElem.isNull() )
1462 QDomElement formatElem = externalGraphicElem.firstChildElement( QStringLiteral(
"Format" ) );
1463 if ( formatElem.isNull() )
1466 QString format = formatElem.firstChild().nodeValue();
1467 if ( format != QLatin1String(
"image/svg+xml" ) )
1469 QgsDebugMsg(
"unsupported External Graphic format found: " + format );
1474 QDomElement onlineResourceElem = externalGraphicElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1475 QDomElement inlineContentElem = externalGraphicElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1476 if ( !onlineResourceElem.isNull() )
1481 else if ( !inlineContentElem.isNull() )
1494 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1495 if ( graphicElem.isNull() )
1498 QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1499 if ( markElem.isNull() )
1502 QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
1503 return !wellKnownNameElem.isNull();
1509 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1510 if ( graphicElem.isNull() )
1513 QDomElement markElem = graphicElem.firstChildElement( QStringLiteral(
"Mark" ) );
1514 if ( markElem.isNull() )
1518 QDomElement formatElem = markElem.firstChildElement( QStringLiteral(
"Format" ) );
1519 if ( formatElem.isNull() )
1522 QString format = formatElem.firstChild().nodeValue();
1523 if ( format != QLatin1String(
"ttf" ) )
1525 QgsDebugMsg(
"unsupported Graphic Mark format found: " + format );
1530 QDomElement onlineResourceElem = markElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1531 QDomElement inlineContentElem = markElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1532 if ( !onlineResourceElem.isNull() )
1535 QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
1536 if ( !markIndexElem.isNull() )
1539 else if ( !inlineContentElem.isNull() )
1554 QDomElement graphicElem = element.firstChildElement( QStringLiteral(
"Graphic" ) );
1555 if ( graphicElem.isNull() )
1559 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
1561 if ( it.key() == QLatin1String(
"widthHeightFactor" ) )
1572 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1573 if ( strokeElem.isNull() )
1576 QDomElement graphicStrokeElem = strokeElem.firstChildElement( QStringLiteral(
"GraphicStroke" ) );
1577 if ( graphicStrokeElem.isNull() )
1585 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1586 if ( fillElem.isNull() )
1589 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1590 if ( graphicFillElem.isNull() )
1593 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1594 if ( graphicElem.isNull() )
1600 QColor fillColor, strokeColor;
1601 double size, strokeWidth;
1602 Qt::PenStyle strokeStyle;
1603 if ( !
wellKnownMarkerFromSld( graphicElem, name, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
1606 if ( name != QLatin1String(
"horline" ) )
1614 double angle = angleFunc.toDouble( &ok );
1626 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1627 if ( fillElem.isNull() )
1630 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1631 if ( graphicFillElem.isNull() )
1651 QDomElement fillElem = element.firstChildElement( QStringLiteral(
"Fill" ) );
1652 QDomElement strokeElem = element.firstChildElement( QStringLiteral(
"Stroke" ) );
1656 bool validFill =
false, validStroke =
false;
1661 Qt::BrushStyle fillStyle;
1663 if (
fillFromSld( fillElem, fillStyle, fillColor ) )
1669 Qt::PenStyle strokeStyle;
1670 double strokeWidth = 1.0, dashOffset = 0.0;
1671 QVector<qreal> customDashPattern;
1673 if (
lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth,
1674 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
1677 if ( validFill || validStroke )
1680 map[QStringLiteral(
"name" )] = QStringLiteral(
"square" );
1681 map[QStringLiteral(
"color" )] =
encodeColor( validFill ? fillColor : Qt::transparent );
1682 map[QStringLiteral(
"color_border" )] =
encodeColor( validStroke ? strokeColor : Qt::transparent );
1683 map[QStringLiteral(
"size" )] = QString::number( 6 );
1684 map[QStringLiteral(
"angle" )] = QString::number( 0 );
1685 map[QStringLiteral(
"offset" )] =
encodePoint( QPointF( 0, 0 ) );
1692 bool validFill =
false, validStroke =
false;
1695 QString name, format;
1697 QColor fillColor, strokeColor;
1698 double strokeWidth = 1.0, size = 0.0,
angle = 0.0;
1702 QDomElement graphicFillElem = fillElem.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1703 if ( !graphicFillElem.isNull() )
1706 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1707 if ( !graphicElem.isNull() )
1713 QDomElement graphicChildElem = graphicElem.firstChildElement();
1714 while ( !graphicChildElem.isNull() )
1716 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
1719 QDomElement wellKnownNameElem = graphicChildElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
1720 if ( !wellKnownNameElem.isNull() )
1722 name = wellKnownNameElem.firstChild().nodeValue();
1728 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) || graphicChildElem.localName() == QLatin1String(
"Mark" ) )
1731 QDomElement formatElem = graphicChildElem.firstChildElement( QStringLiteral(
"Format" ) );
1732 if ( formatElem.isNull() )
1735 format = formatElem.firstChild().nodeValue();
1739 if ( graphicChildElem.localName() == QLatin1String(
"ExternalGraphic" ) && format != QLatin1String(
"image/svg+xml" ) )
1744 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format != QLatin1String(
"ttf" ) )
1748 QDomElement onlineResourceElem = graphicChildElem.firstChildElement( QStringLiteral(
"OnlineResource" ) );
1749 QDomElement inlineContentElem = graphicChildElem.firstChildElement( QStringLiteral(
"InlineContent" ) );
1751 if ( !onlineResourceElem.isNull() )
1753 name = onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) );
1755 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) && format == QLatin1String(
"ttf" ) )
1758 if ( name.startsWith( QLatin1String(
"ttf://" ) ) )
1759 name = name.mid( 6 );
1762 QDomElement markIndexElem = graphicChildElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
1763 if ( markIndexElem.isNull() )
1767 int v = markIndexElem.firstChild().nodeValue().toInt( &ok );
1778 else if ( !inlineContentElem.isNull() )
1788 if ( graphicChildElem.localName() == QLatin1String(
"Mark" ) )
1790 name = QStringLiteral(
"square" );
1797 if ( found && graphicChildElem.localName() == QLatin1String(
"Mark" ) )
1804 Qt::BrushStyle markFillStyle;
1806 QDomElement markFillElem = graphicChildElem.firstChildElement( QStringLiteral(
"Fill" ) );
1807 if (
fillFromSld( markFillElem, markFillStyle, fillColor ) )
1812 Qt::PenStyle strokeStyle;
1813 double strokeWidth = 1.0, dashOffset = 0.0;
1814 QVector<qreal> customDashPattern;
1816 QDomElement markStrokeElem = graphicChildElem.firstChildElement( QStringLiteral(
"Stroke" ) );
1817 if (
lineFromSld( markStrokeElem, strokeStyle, strokeColor, strokeWidth,
1818 nullptr,
nullptr, &customDashPattern, &dashOffset ) )
1825 QDomElement opacityElem = graphicElem.firstChildElement( QStringLiteral(
"Opacity" ) );
1826 if ( !opacityElem.isNull() )
1827 fillColor.setAlpha(
decodeSldAlpha( opacityElem.firstChild().nodeValue() ) );
1829 QDomElement sizeElem = graphicElem.firstChildElement( QStringLiteral(
"Size" ) );
1830 if ( !sizeElem.isNull() )
1833 double v = sizeElem.firstChild().nodeValue().toDouble( &ok );
1842 double v = angleFunc.toDouble( &ok );
1852 if ( validFill || validStroke )
1854 if ( format == QLatin1String(
"image/svg+xml" ) )
1857 map[QStringLiteral(
"name" )] = name;
1858 map[QStringLiteral(
"fill" )] = fillColor.name();
1859 map[QStringLiteral(
"outline" )] = strokeColor.name();
1860 map[QStringLiteral(
"outline-width" )] = QString::number( strokeWidth );
1862 map[QStringLiteral(
"size" )] = QString::number( size );
1864 map[QStringLiteral(
"angle" )] = QString::number(
angle );
1865 if ( !offset.isNull() )
1866 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
1869 else if ( format == QLatin1String(
"ttf" ) )
1872 map[QStringLiteral(
"font" )] = name;
1873 map[QStringLiteral(
"chr" )] = markIndex;
1874 map[QStringLiteral(
"color" )] =
encodeColor( validFill ? fillColor : Qt::transparent );
1876 map[QStringLiteral(
"size" )] = QString::number( size );
1878 map[QStringLiteral(
"angle" )] = QString::number(
angle );
1879 if ( !offset.isNull() )
1880 map[QStringLiteral(
"offset" )] =
encodePoint( offset );
1886 if ( layers.isEmpty() )
1889 layerList << layers;
1896 QString patternName;
1897 switch ( brushStyle )
1902 case Qt::SolidPattern:
1903 if ( color.isValid() )
1906 if ( color.alpha() < 255 )
1911 case Qt::CrossPattern:
1912 case Qt::DiagCrossPattern:
1913 case Qt::HorPattern:
1914 case Qt::VerPattern:
1915 case Qt::BDiagPattern:
1916 case Qt::FDiagPattern:
1917 case Qt::Dense1Pattern:
1918 case Qt::Dense2Pattern:
1919 case Qt::Dense3Pattern:
1920 case Qt::Dense4Pattern:
1921 case Qt::Dense5Pattern:
1922 case Qt::Dense6Pattern:
1923 case Qt::Dense7Pattern:
1928 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( brushStyle ) ) );
1932 QDomElement graphicFillElem = doc.createElement( QStringLiteral(
"se:GraphicFill" ) );
1933 element.appendChild( graphicFillElem );
1935 QDomElement graphicElem = doc.createElement( QStringLiteral(
"se:Graphic" ) );
1936 graphicFillElem.appendChild( graphicElem );
1938 QColor fillColor = patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
1939 QColor strokeColor = !patternName.startsWith( QLatin1String(
"brush://" ) ) ? color : QColor();
1942 wellKnownMarkerToSld( doc, graphicElem, patternName, fillColor, strokeColor, Qt::SolidLine, -1, -1 );
1949 brushStyle = Qt::SolidPattern;
1950 color = QColor( 128, 128, 128 );
1952 if ( element.isNull() )
1954 brushStyle = Qt::NoBrush;
1959 QDomElement graphicFillElem = element.firstChildElement( QStringLiteral(
"GraphicFill" ) );
1961 if ( graphicFillElem.isNull() )
1964 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
1966 QgsDebugMsg( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ) );
1968 if ( it.key() == QLatin1String(
"fill" ) )
1969 color = QColor( it.value() );
1970 else if ( it.key() == QLatin1String(
"fill-opacity" ) )
1976 QDomElement graphicElem = graphicFillElem.firstChildElement( QStringLiteral(
"Graphic" ) );
1977 if ( graphicElem.isNull() )
1980 QString patternName = QStringLiteral(
"square" );
1981 QColor fillColor, strokeColor;
1982 double strokeWidth, size;
1983 Qt::PenStyle strokeStyle;
1984 if ( !
wellKnownMarkerFromSld( graphicElem, patternName, fillColor, strokeColor, strokeStyle, strokeWidth, size ) )
1988 if ( brushStyle == Qt::NoBrush )
1991 QColor
c = patternName.startsWith( QLatin1String(
"brush://" ) ) ? fillColor : strokeColor;
2000 Qt::PenStyle penStyle,
const QColor &color,
double width,
2001 const Qt::PenJoinStyle *penJoinStyle,
const Qt::PenCapStyle *penCapStyle,
2002 const QVector<qreal> *customDashPattern,
double dashOffset )
2004 QVector<qreal> dashPattern;
2005 const QVector<qreal> *pattern = &dashPattern;
2007 if ( penStyle == Qt::CustomDashLine && !customDashPattern )
2009 element.appendChild( doc.createComment( QStringLiteral(
"WARNING: Custom dash pattern required but not provided. Using default dash pattern." ) ) );
2010 penStyle = Qt::DashLine;
2022 dashPattern.push_back( 4.0 );
2023 dashPattern.push_back( 2.0 );
2026 dashPattern.push_back( 1.0 );
2027 dashPattern.push_back( 2.0 );
2029 case Qt::DashDotLine:
2030 dashPattern.push_back( 4.0 );
2031 dashPattern.push_back( 2.0 );
2032 dashPattern.push_back( 1.0 );
2033 dashPattern.push_back( 2.0 );
2035 case Qt::DashDotDotLine:
2036 dashPattern.push_back( 4.0 );
2037 dashPattern.push_back( 2.0 );
2038 dashPattern.push_back( 1.0 );
2039 dashPattern.push_back( 2.0 );
2040 dashPattern.push_back( 1.0 );
2041 dashPattern.push_back( 2.0 );
2044 case Qt::CustomDashLine:
2045 Q_ASSERT( customDashPattern );
2046 pattern = customDashPattern;
2050 element.appendChild( doc.createComment( QStringLiteral(
"Qt::BrushStyle '%1'' not supported yet" ).arg( penStyle ) ) );
2054 if ( color.isValid() )
2057 if ( color.alpha() < 255 )
2064 else if ( width == 0 )
2074 if ( !pattern->isEmpty() )
2084 Qt::PenStyle &penStyle, QColor &color,
double &width,
2085 Qt::PenJoinStyle *penJoinStyle, Qt::PenCapStyle *penCapStyle,
2086 QVector<qreal> *customDashPattern,
double *dashOffset )
2090 penStyle = Qt::SolidLine;
2091 color = QColor( 0, 0, 0 );
2094 *penJoinStyle = Qt::BevelJoin;
2096 *penCapStyle = Qt::SquareCap;
2097 if ( customDashPattern )
2098 customDashPattern->clear();
2102 if ( element.isNull() )
2104 penStyle = Qt::NoPen;
2110 for ( QgsStringMap::iterator it = svgParams.begin(); it != svgParams.end(); ++it )
2112 QgsDebugMsg( QStringLiteral(
"found SvgParameter %1: %2" ).arg( it.key(), it.value() ) );
2114 if ( it.key() == QLatin1String(
"stroke" ) )
2116 color = QColor( it.value() );
2118 else if ( it.key() == QLatin1String(
"stroke-opacity" ) )
2122 else if ( it.key() == QLatin1String(
"stroke-width" ) )
2125 double w = it.value().toDouble( &ok );
2129 else if ( it.key() == QLatin1String(
"stroke-linejoin" ) && penJoinStyle )
2133 else if ( it.key() == QLatin1String(
"stroke-linecap" ) && penCapStyle )
2137 else if ( it.key() == QLatin1String(
"stroke-dasharray" ) )
2140 if ( !dashPattern.isEmpty() )
2144 bool dashPatternFound =
false;
2146 if ( dashPattern.count() == 2 )
2148 if ( dashPattern.at( 0 ) == 4.0 &&
2149 dashPattern.at( 1 ) == 2.0 )
2151 penStyle = Qt::DashLine;
2152 dashPatternFound =
true;
2154 else if ( dashPattern.at( 0 ) == 1.0 &&
2155 dashPattern.at( 1 ) == 2.0 )
2157 penStyle = Qt::DotLine;
2158 dashPatternFound =
true;
2161 else if ( dashPattern.count() == 4 )
2163 if ( dashPattern.at( 0 ) == 4.0 &&
2164 dashPattern.at( 1 ) == 2.0 &&
2165 dashPattern.at( 2 ) == 1.0 &&
2166 dashPattern.at( 3 ) == 2.0 )
2168 penStyle = Qt::DashDotLine;
2169 dashPatternFound =
true;
2172 else if ( dashPattern.count() == 6 )
2174 if ( dashPattern.at( 0 ) == 4.0 &&
2175 dashPattern.at( 1 ) == 2.0 &&
2176 dashPattern.at( 2 ) == 1.0 &&
2177 dashPattern.at( 3 ) == 2.0 &&
2178 dashPattern.at( 4 ) == 1.0 &&
2179 dashPattern.at( 5 ) == 2.0 )
2181 penStyle = Qt::DashDotDotLine;
2182 dashPatternFound =
true;
2187 if ( !dashPatternFound )
2189 if ( customDashPattern )
2191 penStyle = Qt::CustomDashLine;
2192 *customDashPattern = dashPattern;
2196 QgsDebugMsg( QStringLiteral(
"custom dash pattern required but not provided. Using default dash pattern." ) );
2197 penStyle = Qt::DashLine;
2202 else if ( it.key() == QLatin1String(
"stroke-dashoffset" ) && dashOffset )
2205 double d = it.value().toDouble( &ok );
2215 const QString &path,
const QString &mime,
2216 const QColor &color,
double size )
2218 QDomElement externalGraphicElem = doc.createElement( QStringLiteral(
"se:ExternalGraphic" ) );
2219 element.appendChild( externalGraphicElem );
2228 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2230 element.appendChild( sizeElem );
2235 const QString &path,
const QColor &fillColor,
double size,
const QColor &strokeColor,
double strokeWidth )
2242 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Parametric SVG" ) ) );
2246 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Plain SVG fallback, no parameters" ) ) );
2249 graphicElem.appendChild( doc.createComment( QStringLiteral(
"Well known marker fallback" ) ) );
2255 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2257 graphicElem.appendChild( sizeElem );
2265 if ( fillColor.isValid() )
2267 url.addQueryItem( QStringLiteral(
"fill" ), fillColor.name() );
2268 url.addQueryItem( QStringLiteral(
"fill-opacity" ),
encodeSldAlpha( fillColor.alpha() ) );
2272 url.addQueryItem( QStringLiteral(
"fill" ), QStringLiteral(
"#000000" ) );
2273 url.addQueryItem( QStringLiteral(
"fill-opacity" ), QStringLiteral(
"1" ) );
2275 if ( strokeColor.isValid() )
2277 url.addQueryItem( QStringLiteral(
"outline" ), strokeColor.name() );
2278 url.addQueryItem( QStringLiteral(
"outline-opacity" ),
encodeSldAlpha( strokeColor.alpha() ) );
2282 url.addQueryItem( QStringLiteral(
"outline" ), QStringLiteral(
"#000000" ) );
2283 url.addQueryItem( QStringLiteral(
"outline-opacity" ), QStringLiteral(
"1" ) );
2285 url.addQueryItem( QStringLiteral(
"outline-width" ), QString::number( strokeWidth ) );
2286 QString params = url.toString( QUrl::FullyEncoded );
2287 if ( params.isEmpty() )
2293 return basePath +
"?" + params;
2298 QString &path, QString &mime,
2299 QColor &color,
double &size )
2304 QDomElement externalGraphicElem = element.firstChildElement( QStringLiteral(
"ExternalGraphic" ) );
2305 if ( externalGraphicElem.isNull() )
2310 QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2311 if ( !sizeElem.isNull() )
2314 double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2323 const QString &path,
const QString &format,
int *markIndex,
2324 const QColor &color,
double size )
2326 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2327 element.appendChild( markElem );
2333 QDomElement markIndexElem = doc.createElement( QStringLiteral(
"se:MarkIndex" ) );
2334 markIndexElem.appendChild( doc.createTextNode( QString::number( *markIndex ) ) );
2335 markElem.appendChild( markIndexElem );
2339 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2340 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2341 markElem.appendChild( fillElem );
2346 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2348 element.appendChild( sizeElem );
2353 QString &path, QString &format,
int &markIndex,
2354 QColor &color,
double &size )
2362 QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2363 if ( markElem.isNull() )
2368 QDomElement markIndexElem = markElem.firstChildElement( QStringLiteral(
"MarkIndex" ) );
2369 if ( !markIndexElem.isNull() )
2372 int i = markIndexElem.firstChild().nodeValue().toInt( &ok );
2378 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2379 Qt::BrushStyle b = Qt::SolidPattern;
2384 QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2385 if ( !sizeElem.isNull() )
2388 double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2397 const QString &name,
const QColor &color,
const QColor &strokeColor, Qt::PenStyle strokeStyle,
2398 double strokeWidth,
double size )
2400 QDomElement markElem = doc.createElement( QStringLiteral(
"se:Mark" ) );
2401 element.appendChild( markElem );
2403 QDomElement wellKnownNameElem = doc.createElement( QStringLiteral(
"se:WellKnownName" ) );
2404 wellKnownNameElem.appendChild( doc.createTextNode( name ) );
2405 markElem.appendChild( wellKnownNameElem );
2408 if ( color.isValid() )
2410 QDomElement fillElem = doc.createElement( QStringLiteral(
"se:Fill" ) );
2411 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2412 markElem.appendChild( fillElem );
2416 if ( strokeColor.isValid() )
2418 QDomElement strokeElem = doc.createElement( QStringLiteral(
"se:Stroke" ) );
2419 lineToSld( doc, strokeElem, strokeStyle, strokeColor, strokeWidth );
2420 markElem.appendChild( strokeElem );
2426 QDomElement sizeElem = doc.createElement( QStringLiteral(
"se:Size" ) );
2428 element.appendChild( sizeElem );
2433 QString &name, QColor &color, QColor &strokeColor, Qt::PenStyle &strokeStyle,
2434 double &strokeWidth,
double &size )
2438 name = QStringLiteral(
"square" );
2440 strokeColor = QColor( 0, 0, 0 );
2444 QDomElement markElem = element.firstChildElement( QStringLiteral(
"Mark" ) );
2445 if ( markElem.isNull() )
2448 QDomElement wellKnownNameElem = markElem.firstChildElement( QStringLiteral(
"WellKnownName" ) );
2449 if ( !wellKnownNameElem.isNull() )
2451 name = wellKnownNameElem.firstChild().nodeValue();
2452 QgsDebugMsg(
"found Mark with well known name: " + name );
2456 QDomElement fillElem = markElem.firstChildElement( QStringLiteral(
"Fill" ) );
2457 Qt::BrushStyle b = Qt::SolidPattern;
2462 QDomElement strokeElem = markElem.firstChildElement( QStringLiteral(
"Stroke" ) );
2463 lineFromSld( strokeElem, strokeStyle, strokeColor, strokeWidth );
2467 QDomElement sizeElem = element.firstChildElement( QStringLiteral(
"Size" ) );
2468 if ( !sizeElem.isNull() )
2471 double s = sizeElem.firstChild().nodeValue().toDouble( &ok );
2481 if ( !rotationFunc.isEmpty() )
2483 QDomElement rotationElem = doc.createElement( QStringLiteral(
"se:Rotation" ) );
2485 element.appendChild( rotationElem );
2491 QDomElement rotationElem = element.firstChildElement( QStringLiteral(
"Rotation" ) );
2492 if ( !rotationElem.isNull() )
2502 if ( !alphaFunc.isEmpty() )
2504 QDomElement opacityElem = doc.createElement( QStringLiteral(
"se:Opacity" ) );
2506 element.appendChild( opacityElem );
2512 QDomElement opacityElem = element.firstChildElement( QStringLiteral(
"Opacity" ) );
2513 if ( !opacityElem.isNull() )
2522 if ( offset.isNull() )
2525 QDomElement displacementElem = doc.createElement( QStringLiteral(
"se:Displacement" ) );
2526 element.appendChild( displacementElem );
2528 QDomElement dispXElem = doc.createElement( QStringLiteral(
"se:DisplacementX" ) );
2529 dispXElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.x(), 2 ) ) );
2531 QDomElement dispYElem = doc.createElement( QStringLiteral(
"se:DisplacementY" ) );
2532 dispYElem.appendChild( doc.createTextNode(
qgsDoubleToString( offset.y(), 2 ) ) );
2534 displacementElem.appendChild( dispXElem );
2535 displacementElem.appendChild( dispYElem );
2542 QDomElement anchorElem = doc.createElement( QStringLiteral(
"se:AnchorPoint" ) );
2543 element.appendChild( anchorElem );
2545 QDomElement anchorXElem = doc.createElement( QStringLiteral(
"se:AnchorPointX" ) );
2546 anchorXElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.x() ) ) );
2548 QDomElement anchorYElem = doc.createElement( QStringLiteral(
"se:AnchorPointY" ) );
2549 anchorYElem.appendChild( doc.createTextNode(
qgsDoubleToString( anchor.y() ) ) );
2551 anchorElem.appendChild( anchorXElem );
2552 anchorElem.appendChild( anchorYElem );
2557 offset = QPointF( 0, 0 );
2559 QDomElement displacementElem = element.firstChildElement( QStringLiteral(
"Displacement" ) );
2560 if ( displacementElem.isNull() )
2563 QDomElement dispXElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementX" ) );
2564 if ( !dispXElem.isNull() )
2567 double offsetX = dispXElem.firstChild().nodeValue().toDouble( &ok );
2569 offset.setX( offsetX );
2572 QDomElement dispYElem = displacementElem.firstChildElement( QStringLiteral(
"DisplacementY" ) );
2573 if ( !dispYElem.isNull() )
2576 double offsetY = dispYElem.firstChild().nodeValue().toDouble( &ok );
2578 offset.setY( offsetY );
2585 const QString &label,
const QFont &font,
2586 const QColor &color,
double size )
2588 QDomElement labelElem = doc.createElement( QStringLiteral(
"se:Label" ) );
2589 labelElem.appendChild( doc.createTextNode( label ) );
2590 element.appendChild( labelElem );
2592 QDomElement fontElem = doc.createElement( QStringLiteral(
"se:Font" ) );
2593 element.appendChild( fontElem );
2597 fontElem.appendChild( createSldParameterElement( doc,
"font-style",
encodeSldFontStyle( font.style() ) ) );
2598 fontElem.appendChild( createSldParameterElement( doc,
"font-weight",
encodeSldFontWeight( font.weight() ) ) );
2603 if ( color.isValid() )
2605 QDomElement fillElem = doc.createElement( QStringLiteral(
"Fill" ) );
2606 fillToSld( doc, fillElem, Qt::SolidPattern, color );
2607 element.appendChild( fillElem );
2612 Qt::PenJoinStyle joinStyle,
2613 Qt::PenCapStyle capStyle,
2615 const QVector<qreal> *dashPattern )
2618 penStyle.append(
"PEN(" );
2619 penStyle.append(
"c:" );
2620 penStyle.append(
c.name() );
2621 penStyle.append(
",w:" );
2623 penStyle.append( QString::number( width * mmScaleFactor ) );
2624 penStyle.append(
"mm" );
2627 if ( dashPattern && !dashPattern->isEmpty() )
2629 penStyle.append(
",p:\"" );
2630 QVector<qreal>::const_iterator pIt = dashPattern->constBegin();
2631 for ( ; pIt != dashPattern->constEnd(); ++pIt )
2633 if ( pIt != dashPattern->constBegin() )
2635 penStyle.append(
' ' );
2637 penStyle.append( QString::number( *pIt * mapUnitScaleFactor ) );
2638 penStyle.append(
'g' );
2640 penStyle.append(
'\"' );
2644 penStyle.append(
",cap:" );
2648 penStyle.append(
'p' );
2651 penStyle.append(
'r' );
2655 penStyle.append(
'b' );
2659 penStyle.append(
",j:" );
2660 switch ( joinStyle )
2663 penStyle.append(
'b' );
2666 penStyle.append(
'r' );
2670 penStyle.append(
'm' );
2676 penStyle.append(
",dp:" );
2677 penStyle.append( QString::number( offset * mapUnitScaleFactor ) );
2678 penStyle.append(
'g' );
2681 penStyle.append(
')' );
2688 brushStyle.append(
"BRUSH(" );
2689 brushStyle.append(
"fc:" );
2690 brushStyle.append( fillColor.name() );
2691 brushStyle.append(
')' );
2697 if ( geomFunc.isEmpty() )
2700 QDomElement geometryElem = doc.createElement( QStringLiteral(
"Geometry" ) );
2701 element.appendChild( geometryElem );
2731 QDomElement geometryElem = element.firstChildElement( QStringLiteral(
"Geometry" ) );
2732 if ( geometryElem.isNull() )
2744 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " +
function ) );
2748 if ( !filterElem.isNull() )
2749 element.appendChild( filterElem );
2760 element.appendChild( doc.createComment(
"Parser Error: " + expr.
parserErrorString() +
" - Expression was: " +
function ) );
2764 if ( !filterElem.isNull() )
2765 element.appendChild( filterElem );
2772 QDomElement elem = element;
2773 if ( element.tagName() != QLatin1String(
"Filter" ) )
2775 QDomNodeList filterNodes = element.elementsByTagName( QStringLiteral(
"Filter" ) );
2776 if ( !filterNodes.isEmpty() )
2778 elem = filterNodes.at( 0 ).toElement();
2782 if ( elem.isNull() )
2807 const QString &path,
const QString &format )
2811 QDomElement onlineResourceElem = doc.createElement( QStringLiteral(
"se:OnlineResource" ) );
2812 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:type" ), QStringLiteral(
"simple" ) );
2813 onlineResourceElem.setAttribute( QStringLiteral(
"xlink:href" ), url );
2814 element.appendChild( onlineResourceElem );
2816 QDomElement formatElem = doc.createElement( QStringLiteral(
"se:Format" ) );
2817 formatElem.appendChild( doc.createTextNode( format ) );
2818 element.appendChild( formatElem );
2825 QDomElement onlineResourceElem = element.firstChildElement( QStringLiteral(
"OnlineResource" ) );
2826 if ( onlineResourceElem.isNull() )
2829 path = onlineResourceElem.attributeNS( QStringLiteral(
"http://www.w3.org/1999/xlink" ), QStringLiteral(
"href" ) );
2831 QDomElement formatElem = element.firstChildElement( QStringLiteral(
"Format" ) );
2832 if ( formatElem.isNull() )
2835 format = formatElem.firstChild().nodeValue();
2842 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:SvgParameter" ) );
2843 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
2844 nodeElem.appendChild( doc.createTextNode( value ) );
2853 QDomElement paramElem = element.firstChildElement();
2854 while ( !paramElem.isNull() )
2856 if ( paramElem.localName() == QLatin1String(
"SvgParameter" ) || paramElem.localName() == QLatin1String(
"CssParameter" ) )
2858 QString name = paramElem.attribute( QStringLiteral(
"name" ) );
2859 if ( paramElem.firstChild().nodeType() == QDomNode::TextNode )
2861 value = paramElem.firstChild().nodeValue();
2865 if ( paramElem.firstChild().nodeType() == QDomNode::ElementNode &&
2866 paramElem.firstChild().localName() == QLatin1String(
"Literal" ) )
2868 QgsDebugMsg( paramElem.firstChild().localName() );
2869 value = paramElem.firstChild().firstChild().nodeValue();
2873 QgsDebugMsg( QStringLiteral(
"unexpected child of %1" ).arg( paramElem.localName() ) );
2877 if ( !name.isEmpty() && !value.isEmpty() )
2878 params[ name ] = value;
2881 paramElem = paramElem.nextSiblingElement();
2889 QDomElement nodeElem = doc.createElement( QStringLiteral(
"se:VendorOption" ) );
2890 nodeElem.setAttribute( QStringLiteral(
"name" ), name );
2891 nodeElem.appendChild( doc.createTextNode( value ) );
2899 QDomElement paramElem = element.firstChildElement( QStringLiteral(
"VendorOption" ) );
2900 while ( !paramElem.isNull() )
2902 QString name = paramElem.attribute( QStringLiteral(
"name" ) );
2903 QString value = paramElem.firstChild().nodeValue();
2905 if ( !name.isEmpty() && !value.isEmpty() )
2906 params[ name ] = value;
2908 paramElem = paramElem.nextSiblingElement( QStringLiteral(
"VendorOption" ) );
2918 QDomElement e = element.firstChildElement();
2919 while ( !e.isNull() )
2921 if ( e.tagName() == QLatin1String(
"prop" ) )
2923 QString propKey = e.attribute( QStringLiteral(
"k" ) );
2924 QString propValue = e.attribute( QStringLiteral(
"v" ) );
2925 props[propKey] = propValue;
2927 e = e.nextSiblingElement();
2935 for ( QgsStringMap::iterator it = props.begin(); it != props.end(); ++it )
2937 QDomElement propEl = doc.createElement( QStringLiteral(
"prop" ) );
2938 propEl.setAttribute( QStringLiteral(
"k" ), it.key() );
2939 propEl.setAttribute( QStringLiteral(
"v" ), it.value() );
2940 element.appendChild( propEl );
2949 QDomElement e = element.firstChildElement();
2951 while ( !e.isNull() )
2953 if ( e.tagName() == QLatin1String(
"symbol" ) )
2957 symbols.insert( e.attribute( QStringLiteral(
"name" ) ), symbol );
2963 e = e.nextSiblingElement();
2970 QStringList subsymbols;
2972 for ( QMap<QString, QgsSymbol *>::iterator it = symbols.begin(); it != symbols.end(); ++it )
2974 if ( it.key()[0] !=
'@' )
2978 subsymbols.append( it.key() );
2980 QStringList parts = it.key().split(
'@' );
2981 if ( parts.count() < 3 )
2983 QgsDebugMsg(
"found subsymbol with invalid name: " + it.key() );
2987 QString symname = parts[1];
2988 int symlayer = parts[2].toInt();
2990 if ( !symbols.contains( symname ) )
2992 QgsDebugMsg(
"subsymbol references invalid symbol: " + symname );
3000 QgsDebugMsg(
"subsymbol references invalid symbol layer: " + QString::number( symlayer ) );
3009 QgsDebugMsg(
"symbol layer refused subsymbol: " + it.key() );
3016 for (
int i = 0; i < subsymbols.count(); i++ )
3017 symbols.take( subsymbols[i] );
3024 QDomElement symbolsElem = doc.createElement( tagName );
3027 for ( QMap<QString, QgsSymbol *>::iterator its = symbols.begin(); its != symbols.end(); ++its )
3029 QDomElement symEl =
saveSymbol( its.key(), its.value(), doc, context );
3030 symbolsElem.appendChild( symEl );
3038 qDeleteAll( symbols );
3047 std::unique_ptr< QMimeData >mimeData(
new QMimeData );
3049 QDomDocument symbolDoc;
3051 symbolDoc.appendChild( symbolElem );
3052 mimeData->setText( symbolDoc.toString() );
3055 mimeData->setColorData( symbol->
color() );
3057 return mimeData.release();
3065 QString text = data->text();
3066 if ( !text.isEmpty() )
3071 if ( doc.setContent( text ) )
3073 elem = doc.documentElement();
3075 if ( elem.nodeName() != QStringLiteral(
"symbol" ) )
3076 elem = elem.firstChildElement( QStringLiteral(
"symbol" ) );
3087 QString rampType = element.attribute( QStringLiteral(
"type" ) );
3092 if ( rampType == QLatin1String(
"gradient" ) )
3094 else if ( rampType == QLatin1String(
"random" ) )
3096 else if ( rampType == QLatin1String(
"colorbrewer" ) )
3098 else if ( rampType == QLatin1String(
"cpt-city" ) )
3100 else if ( rampType == QLatin1String(
"preset" ) )
3104 QgsDebugMsg(
"unknown colorramp type " + rampType );
3112 QDomElement rampEl = doc.createElement( QStringLiteral(
"colorramp" ) );
3113 rampEl.setAttribute( QStringLiteral(
"type" ), ramp->
type() );
3114 rampEl.setAttribute( QStringLiteral(
"name" ), name );
3122 QVariantMap rampMap;
3124 rampMap.insert( QStringLiteral(
"type" ), ramp->
type() );
3125 rampMap.insert( QStringLiteral(
"name" ), name );
3129 QVariantMap propertyMap;
3130 for (
auto property = properties.constBegin(); property != properties.constEnd(); ++property )
3132 propertyMap.insert( property.key(), property.value() );
3135 rampMap.insert( QStringLiteral(
"properties" ), propertyMap );
3141 QVariantMap rampMap = value.toMap();
3143 QString rampType = rampMap.
value( QStringLiteral(
"type" ) ).toString();
3146 QVariantMap propertyMap = rampMap.value( QStringLiteral(
"properties" ) ).toMap();
3149 for (
auto property = propertyMap.constBegin(); property != propertyMap.constEnd(); ++property )
3151 props.insert( property.key(), property.value().toString() );
3154 if ( rampType == QLatin1String(
"gradient" ) )
3156 else if ( rampType == QLatin1String(
"random" ) )
3158 else if ( rampType == QLatin1String(
"colorbrewer" ) )
3160 else if ( rampType == QLatin1String(
"cpt-city" ) )
3162 else if ( rampType == QLatin1String(
"preset" ) )
3166 QgsDebugMsg(
"unknown colorramp type " + rampType );
3173 if ( !color.isValid() )
3180 return color.name();
3185 QList<QColor> colors;
3188 QStringList components = colorStr.simplified().split( QRegExp(
"(,|\\s)" ) );
3189 QStringList::iterator it = components.begin();
3190 for ( ; it != components.end(); ++it )
3193 if ( result.isValid() )
3198 if ( colors.length() > 0 )
3204 components = colorStr.split( QRegExp(
"(,|\n)" ) );
3205 it = components.begin();
3206 for ( ; it != components.end(); ++it )
3209 if ( result.isValid() )
3214 if ( colors.length() > 0 )
3220 components = colorStr.simplified().split( QString(
' ' ) );
3221 it = components.begin();
3222 for ( ; it != components.end(); ++it )
3225 if ( result.isValid() )
3230 if ( colors.length() > 0 )
3236 components = colorStr.split(
'\n' );
3237 it = components.begin();
3238 for ( ; it != components.end(); ++it )
3241 if ( result.isValid() )
3254 QMimeData *mimeData =
new QMimeData;
3255 mimeData->setColorData( QVariant( color ) );
3256 mimeData->setText( color.name() );
3263 QColor mimeColor = mimeData->colorData().value<QColor>();
3264 if ( mimeColor.isValid() )
3273 if ( textColor.isValid() )
3287 if ( data->hasFormat( QStringLiteral(
"text/xml" ) ) )
3290 QByteArray encodedData = data->data( QStringLiteral(
"text/xml" ) );
3291 QDomDocument xmlDoc;
3292 xmlDoc.setContent( encodedData );
3294 QDomElement dragDataElem = xmlDoc.documentElement();
3295 if ( dragDataElem.tagName() == QLatin1String(
"ColorSchemeModelDragData" ) )
3297 QDomNodeList nodeList = dragDataElem.childNodes();
3298 int nChildNodes = nodeList.size();
3299 QDomElement currentElem;
3301 for (
int i = 0; i < nChildNodes; ++i )
3303 currentElem = nodeList.at( i ).toElement();
3304 if ( currentElem.isNull() )
3309 QPair< QColor, QString> namedColor;
3311 namedColor.second = currentElem.attribute( QStringLiteral(
"label" ), QString() );
3313 mimeColors << namedColor;
3318 if ( mimeColors.length() == 0 && data->hasFormat( QStringLiteral(
"application/x-colorobject-list" ) ) )
3321 QByteArray encodedData = data->data( QStringLiteral(
"application/x-colorobject-list" ) );
3322 QDomDocument xmlDoc;
3323 xmlDoc.setContent( encodedData );
3325 QDomNodeList colorsNodes = xmlDoc.elementsByTagName( QStringLiteral(
"colors" ) );
3326 if ( colorsNodes.length() > 0 )
3328 QDomElement colorsElem = colorsNodes.at( 0 ).toElement();
3329 QDomNodeList colorNodeList = colorsElem.childNodes();
3330 int nChildNodes = colorNodeList.size();
3331 QDomElement currentElem;
3333 for (
int i = 0; i < nChildNodes; ++i )
3336 currentElem = colorNodeList.at( i ).toElement();
3337 if ( currentElem.isNull() )
3342 QDomNodeList colorNodes = currentElem.elementsByTagName( QStringLiteral(
"color" ) );
3343 QDomNodeList nameNodes = currentElem.elementsByTagName( QStringLiteral(
"name" ) );
3345 if ( colorNodes.length() > 0 )
3347 QDomElement colorElem = colorNodes.at( 0 ).toElement();
3349 QStringList colorParts = colorElem.text().simplified().split(
' ' );
3350 if ( colorParts.length() < 3 )
3355 int red = colorParts.at( 0 ).toDouble() * 255;
3356 int green = colorParts.at( 1 ).toDouble() * 255;
3357 int blue = colorParts.at( 2 ).toDouble() * 255;
3358 QPair< QColor, QString> namedColor;
3359 namedColor.first = QColor( red, green, blue );
3360 if ( nameNodes.length() > 0 )
3362 QDomElement nameElem = nameNodes.at( 0 ).toElement();
3363 namedColor.second = nameElem.text();
3365 mimeColors << namedColor;
3371 if ( mimeColors.length() == 0 && data->hasText() )
3375 QList< QColor >::iterator it = parsedColors.begin();
3376 for ( ; it != parsedColors.end(); ++it )
3378 mimeColors << qMakePair( *it, QString() );
3382 if ( mimeColors.length() == 0 && data->hasColor() )
3385 QColor mimeColor = data->colorData().value<QColor>();
3386 if ( mimeColor.isValid() )
3388 mimeColors << qMakePair( mimeColor, QString() );
3398 QMimeData *mimeData =
new QMimeData();
3399 QDomDocument xmlDoc;
3400 QDomElement xmlRootElement = xmlDoc.createElement( QStringLiteral(
"ColorSchemeModelDragData" ) );
3401 xmlDoc.appendChild( xmlRootElement );
3403 QgsNamedColorList::const_iterator colorIt = colorList.constBegin();
3404 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3406 QDomElement namedColor = xmlDoc.createElement( QStringLiteral(
"NamedColor" ) );
3408 namedColor.setAttribute( QStringLiteral(
"label" ), ( *colorIt ).second );
3409 xmlRootElement.appendChild( namedColor );
3411 mimeData->setData( QStringLiteral(
"text/xml" ), xmlDoc.toByteArray() );
3419 colorIt = colorList.constBegin();
3420 QStringList colorListString;
3421 for ( ; colorIt != colorList.constEnd(); ++colorIt )
3423 colorListString << ( *colorIt ).first.name();
3425 mimeData->setText( colorListString.join( QStringLiteral(
"\n" ) ) );
3428 if ( colorList.length() > 0 )
3430 mimeData->setColorData( QVariant( colorList.at( 0 ).first ) );
3438 if ( !file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
3443 QTextStream stream( &file );
3444 stream <<
"GIMP Palette" << endl;
3445 if ( paletteName.isEmpty() )
3447 stream <<
"Name: QGIS Palette" << endl;
3451 stream <<
"Name: " << paletteName << endl;
3453 stream <<
"Columns: 4" << endl;
3454 stream <<
'#' << endl;
3456 for ( QgsNamedColorList::ConstIterator colorIt = colors.constBegin(); colorIt != colors.constEnd(); ++colorIt )
3458 QColor color = ( *colorIt ).first;
3459 if ( !color.isValid() )
3463 stream << QStringLiteral(
"%1 %2 %3" ).arg( color.red(), 3 ).arg( color.green(), 3 ).arg( color.blue(), 3 );
3464 stream <<
"\t" << ( ( *colorIt ).second.isEmpty() ? color.name() : ( *colorIt ).second ) << endl;
3475 if ( !file.open( QIODevice::ReadOnly ) )
3478 return importedColors;
3481 QTextStream in( &file );
3483 QString line = in.readLine();
3484 if ( !line.startsWith( QLatin1String(
"GIMP Palette" ) ) )
3487 return importedColors;
3491 while ( !in.atEnd() && !line.startsWith( QLatin1String(
"Name:" ) ) && !line.startsWith(
'#' ) )
3493 line = in.readLine();
3495 if ( line.startsWith( QLatin1String(
"Name:" ) ) )
3497 QRegExp nameRx(
"Name:\\s*(\\S.*)$" );
3498 if ( nameRx.indexIn( line ) != -1 )
3500 name = nameRx.cap( 1 );
3505 while ( !in.atEnd() && !line.startsWith(
'#' ) )
3507 line = in.readLine();
3512 return importedColors;
3516 QRegExp rx(
"^\\s*(\\d+)\\s+(\\d+)\\s+(\\d+)(\\s.*)?$" );
3517 while ( !in.atEnd() )
3519 line = in.readLine();
3520 if ( rx.indexIn( line ) == -1 )
3524 int red = rx.cap( 1 ).toInt();
3525 int green = rx.cap( 2 ).toInt();
3526 int blue = rx.cap( 3 ).toInt();
3527 QColor color = QColor( red, green, blue );
3528 if ( !color.isValid() )
3535 if ( rx.captureCount() > 3 )
3537 label = rx.cap( 4 ).simplified();
3544 importedColors << qMakePair( color, label );
3549 return importedColors;
3562 QRegExp hexColorAlphaRx(
"^\\s*#?([0-9a-fA-F]{6})([0-9a-fA-F]{2})\\s*$" );
3563 int hexColorIndex = hexColorAlphaRx.indexIn( colorStr );
3566 if ( hexColorIndex == -1 && QColor::isValidColor( colorStr ) )
3569 parsedColor.setNamedColor( colorStr );
3570 if ( parsedColor.isValid() )
3572 containsAlpha =
false;
3578 if ( hexColorIndex > -1 )
3580 QString hexColor = hexColorAlphaRx.cap( 1 );
3581 parsedColor.setNamedColor( QStringLiteral(
"#" ) + hexColor );
3583 int alphaHex = hexColorAlphaRx.cap( 2 ).toInt( &alphaOk, 16 );
3585 if ( parsedColor.isValid() && alphaOk )
3587 parsedColor.setAlpha( alphaHex );
3588 containsAlpha =
true;
3596 QRegExp hexColorRx2(
"^\\s*(?:[0-9a-fA-F]{3}){1,2}\\s*$" );
3597 if ( hexColorRx2.indexIn( colorStr ) != -1 )
3600 parsedColor.setNamedColor( QStringLiteral(
"#" ) + colorStr );
3601 if ( parsedColor.isValid() )
3603 containsAlpha =
false;
3610 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*$" );
3611 if ( rgbFormatRx.indexIn( colorStr ) != -1 )
3613 int r = rgbFormatRx.cap( 1 ).toInt();
3614 int g = rgbFormatRx.cap( 2 ).toInt();
3615 int b = rgbFormatRx.cap( 3 ).toInt();
3616 parsedColor.setRgb( r, g, b );
3617 if ( parsedColor.isValid() )
3619 containsAlpha =
false;
3625 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*$" );
3626 if ( rgbPercentFormatRx.indexIn( colorStr ) != -1 )
3628 int r = std::round( rgbPercentFormatRx.cap( 1 ).toDouble() * 2.55 );
3629 int g = std::round( rgbPercentFormatRx.cap( 2 ).toDouble() * 2.55 );
3630 int b = std::round( rgbPercentFormatRx.cap( 3 ).toDouble() * 2.55 );
3631 parsedColor.setRgb( r, g, b );
3632 if ( parsedColor.isValid() )
3634 containsAlpha =
false;
3640 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*$" );
3641 if ( rgbaFormatRx.indexIn( colorStr ) != -1 )
3643 int r = rgbaFormatRx.cap( 1 ).toInt();
3644 int g = rgbaFormatRx.cap( 2 ).toInt();
3645 int b = rgbaFormatRx.cap( 3 ).toInt();
3646 int a = std::round( rgbaFormatRx.cap( 4 ).toDouble() * 255.0 );
3647 parsedColor.setRgb( r, g, b, a );
3648 if ( parsedColor.isValid() )
3650 containsAlpha =
true;
3656 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*$" );
3657 if ( rgbaPercentFormatRx.indexIn( colorStr ) != -1 )
3659 int r = std::round( rgbaPercentFormatRx.cap( 1 ).toDouble() * 2.55 );
3660 int g = std::round( rgbaPercentFormatRx.cap( 2 ).toDouble() * 2.55 );
3661 int b = std::round( rgbaPercentFormatRx.cap( 3 ).toDouble() * 2.55 );
3662 int a = std::round( rgbaPercentFormatRx.cap( 4 ).toDouble() * 255.0 );
3663 parsedColor.setRgb( r, g, b, a );
3664 if ( parsedColor.isValid() )
3666 containsAlpha =
true;
3683 QImage::Format format = image->format();
3684 if ( format != QImage::Format_ARGB32_Premultiplied && format != QImage::Format_ARGB32 )
3686 QgsDebugMsg( QStringLiteral(
"no alpha channel." ) );
3691 for (
int heightIndex = 0; heightIndex < image->height(); ++heightIndex )
3693 QRgb *scanLine =
reinterpret_cast< QRgb *
>( image->scanLine( heightIndex ) );
3694 for (
int widthIndex = 0; widthIndex < image->width(); ++widthIndex )
3696 myRgb = scanLine[widthIndex];
3697 if ( format == QImage::Format_ARGB32_Premultiplied )
3698 scanLine[widthIndex] = qRgba( opacity * qRed( myRgb ), opacity * qGreen( myRgb ), opacity * qBlue( myRgb ), opacity * qAlpha( myRgb ) );
3700 scanLine[widthIndex] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), opacity * qAlpha( myRgb ) );
3708 int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
3709 int alpha = ( radius < 1 ) ? 16 : ( radius > 17 ) ? 1 : tab[radius - 1];
3711 if ( image.format() != QImage::Format_ARGB32_Premultiplied
3712 && image.format() != QImage::Format_RGB32 )
3714 image = image.convertToFormat( QImage::Format_ARGB32_Premultiplied );
3717 int r1 = rect.top();
3718 int r2 = rect.bottom();
3719 int c1 = rect.left();
3720 int c2 = rect.right();
3722 int bpl = image.bytesPerLine();
3730 i1 = i2 = ( QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3 );
3732 for (
int col = c1; col <= c2; col++ )
3734 p = image.scanLine( r1 ) + col * 4;
3735 for (
int i = i1; i <= i2; i++ )
3736 rgba[i] = p[i] << 4;
3739 for (
int j = r1; j < r2; j++, p += bpl )
3740 for (
int i = i1; i <= i2; i++ )
3741 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
3744 for (
int row = r1; row <= r2; row++ )
3746 p = image.scanLine( row ) + c1 * 4;
3747 for (
int i = i1; i <= i2; i++ )
3748 rgba[i] = p[i] << 4;
3751 for (
int j = c1; j < c2; j++, p += 4 )
3752 for (
int i = i1; i <= i2; i++ )
3753 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
3756 for (
int col = c1; col <= c2; col++ )
3758 p = image.scanLine( r2 ) + col * 4;
3759 for (
int i = i1; i <= i2; i++ )
3760 rgba[i] = p[i] << 4;
3763 for (
int j = r1; j < r2; j++, p -= bpl )
3764 for (
int i = i1; i <= i2; i++ )
3765 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
3768 for (
int row = r1; row <= r2; row++ )
3770 p = image.scanLine( row ) + c2 * 4;
3771 for (
int i = i1; i <= i2; i++ )
3772 rgba[i] = p[i] << 4;
3775 for (
int j = c1; j < c2; j++, p -= 4 )
3776 for (
int i = i1; i <= i2; i++ )
3777 p[i] = ( rgba[i] += ( ( p[i] << 4 ) - rgba[i] ) * alpha / 16 ) >> 4;
3783 if ( alpha != 255 && alpha > 0 )
3787 double alphaFactor = alpha / 255.;
3788 int r = 0, g = 0, b = 0;
3789 rgb.getRgb( &r, &g, &b );
3794 rgb.setRgb( r, g, b, alpha );
3796 else if ( alpha == 0 )
3798 rgb.setRgb( 0, 0, 0, 0 );
3804 if ( order == Qt::AscendingOrder )
3818 double dx = directionPoint.x() - startPoint.x();
3819 double dy = directionPoint.y() - startPoint.y();
3820 double length = std::sqrt( dx * dx + dy * dy );
3821 double scaleFactor = distance / length;
3822 return QPointF( startPoint.x() + dx * scaleFactor, startPoint.y() + dy * scaleFactor );
3832 for (
int i = 0; i < svgPaths.size(); i++ )
3834 QDir dir( svgPaths[i] );
3835 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
3836 for (
const QString &item : svgSubPaths )
3838 svgPaths.insert( i + 1, dir.path() +
'/' + item );
3841 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
3842 for (
const QString &item : svgFiles )
3845 list.append( dir.path() +
'/' + item );
3857 QStringList svgPaths;
3858 svgPaths.append( directory );
3860 for (
int i = 0; i < svgPaths.size(); i++ )
3862 QDir dir( svgPaths[i] );
3863 const auto svgSubPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
3864 for (
const QString &item : svgSubPaths )
3866 svgPaths.insert( i + 1, dir.path() +
'/' + item );
3869 const auto svgFiles = dir.entryList( QStringList(
"*.svg" ), QDir::Files );
3870 for (
const QString &item : svgFiles )
3872 list.append( dir.path() +
'/' + item );
3884 if ( n.startsWith( QLatin1String(
"base64:" ) ) )
3888 if ( QFileInfo::exists( n ) )
3889 return QFileInfo( n ).canonicalFilePath();
3893 if ( name.contains( QLatin1String(
"://" ) ) )
3896 if ( url.isValid() && !url.scheme().isEmpty() )
3898 if ( url.scheme().compare( QLatin1String(
"file" ), Qt::CaseInsensitive ) == 0 )
3901 name = url.toLocalFile();
3902 if ( QFile( name ).exists() )
3904 return QFileInfo( name ).canonicalFilePath();
3918 for (
int i = 0; i < svgPaths.size(); i++ )
3920 QString svgPath = svgPaths[i];
3921 if ( svgPath.endsWith( QChar(
'/' ) ) )
3932 QString myLocalPath = svgPath + QDir::separator() + name;
3935 if ( QFile( myLocalPath ).exists() )
3938 return QFileInfo( myLocalPath ).canonicalFilePath();
3942 return pathResolver.
readPath( name );
3950 if ( p.startsWith( QLatin1String(
"base64:" ) ) )
3953 if ( !QFileInfo::exists( p ) )
3956 QString path = QFileInfo( p ).canonicalFilePath();
3960 bool isInSvgPaths =
false;
3961 for (
int i = 0; i < svgPaths.size(); i++ )
3963 QString dir = QFileInfo( svgPaths[i] ).canonicalFilePath();
3965 if ( !dir.isEmpty() && path.startsWith( dir ) )
3967 path = path.mid( dir.size() + 1 );
3968 isInSvgPaths =
true;
3983 double cx = 0, cy = 0;
3984 double area, sum = 0;
3985 for (
int i = points.count() - 1, j = 0; j < points.count(); i = j++ )
3987 const QPointF &p1 = points[i];
3988 const QPointF &p2 = points[j];
3989 area = p1.x() * p2.y() - p1.y() * p2.x();
3991 cx += ( p1.x() + p2.x() ) * area;
3992 cy += ( p1.y() + p2.y() ) * area;
3999 if ( points.count() >= 2 )
4000 return QPointF( ( points[0].x() + points[1].x() ) / 2, ( points[0].y() + points[1].y() ) / 2 );
4001 else if ( points.count() == 1 )
4009 return QPointF( cx, cy );
4016 if ( ( rings && rings->count() > 0 ) || !
pointInPolygon( points, centroid ) )
4018 unsigned int i, pointCount = points.count();
4020 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( points[i].x(), points[i].y() );
4026 for (
auto ringIt = rings->constBegin(); ringIt != rings->constEnd(); ++ringIt )
4028 pointCount = ( *ringIt ).count();
4030 for ( i = 0; i < pointCount; ++i ) polyline[i] =
QgsPointXY( ( *ringIt )[i].x(), ( *ringIt )[i].y() );
4036 if ( !pointOnSurfaceGeom.
isNull() )
4039 centroid.
setX( point.
x() );
4040 centroid.setY( point.
y() );
4045 return QPointF( centroid.x(), centroid.y() );
4050 bool inside =
false;
4052 double x = point.x();
4053 double y = point.y();
4055 for (
int i = 0, j = points.count() - 1; i < points.count(); i++ )
4057 const QPointF &p1 = points[i];
4058 const QPointF &p2 = points[j];
4063 if ( ( p1.y() < y && p2.y() >= y ) || ( p2.y() < y && p1.y() >= y ) )
4065 if ( p1.x() + ( y - p1.y() ) / ( p2.y() - p1.y() ) * ( p2.x() - p1.x() ) <= x )
4076 if ( fieldOrExpression.isEmpty() )
4111 QList<double> breaks;
4114 breaks.append( maximum );
4118 int minimumCount =
static_cast< int >( classes ) / 3;
4119 double shrink = 0.75;
4120 double highBias = 1.5;
4121 double adjustBias = 0.5 + 1.5 * highBias;
4122 int divisions = classes;
4123 double h = highBias;
4126 double dx = maximum - minimum;
4136 cell = std::max( std::fabs( minimum ), std::fabs( maximum ) );
4137 if ( adjustBias >= 1.5 * h + 0.5 )
4139 U = 1 + ( 1.0 / ( 1 + h ) );
4143 U = 1 + ( 1.5 / ( 1 + adjustBias ) );
4145 small = dx < ( cell * U * std::max( 1, divisions ) * 1e-07 * 3.0 );
4152 cell = 9 + cell / 10;
4153 cell = cell * shrink;
4155 if ( minimumCount > 1 )
4157 cell = cell / minimumCount;
4163 if ( divisions > 1 )
4165 cell = cell / divisions;
4168 if ( cell < 20 * 1e-07 )
4173 double base = std::pow( 10.0, std::floor( std::log10( cell ) ) );
4175 if ( ( 2 * base ) - cell < h * ( cell - unit ) )
4178 if ( ( 5 * base ) - cell < adjustBias * ( cell - unit ) )
4181 if ( ( 10.0 * base ) - cell < h * ( cell - unit ) )
4188 int start = std::floor( minimum / unit + 1e-07 );
4189 int end = std::ceil( maximum / unit - 1e-07 );
4192 while ( start * unit > minimum + ( 1e-07 * unit ) )
4196 while ( end * unit < maximum - ( 1e-07 * unit ) )
4200 QgsDebugMsg( QStringLiteral(
"pretty classes: %1" ).arg( end ) );
4204 int k = std::floor( 0.5 + end - start );
4205 if ( k < minimumCount )
4207 k = minimumCount - k;
4211 start = start - k / 2 + k % 2;
4215 start = start - k / 2;
4216 end = end + k / 2 + k % 2;
4219 double minimumBreak = start * unit;
4221 int count = end - start;
4223 breaks.reserve( count );
4224 for (
int i = 1; i < count + 1; i++ )
4226 breaks.append( minimumBreak + i * unit );
4229 if ( breaks.isEmpty() )
4232 if ( breaks.first() < minimum )
4234 breaks[0] = minimum;
4236 if ( breaks.last() > maximum )
4238 breaks[breaks.count() - 1] = maximum;
4243 if ( minimum < 0.0 && maximum > 0.0 )
4245 QList<double> breaksMinusZero;
4246 for (
int i = 0; i < breaks.count(); i++ )
4248 breaksMinusZero.append( breaks[i] - 0.0 );
4251 for (
int i = 1; i < breaks.count(); i++ )
4253 if ( std::abs( breaksMinusZero[i] ) < std::abs( breaksMinusZero[i - 1] ) )
4256 breaks[posOfMin] = 0.0;
4265 bool roundToUnit =
false;
4268 if ( props.contains( QStringLiteral(
"uomScale" ) ) )
4271 scale = props.value( QStringLiteral(
"uomScale" ) ).toDouble( &ok );
4280 if ( props.value( QStringLiteral(
"uom" ) ) == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
4305 scale = 1 / 0.28 * 25.4;
4329 double rescaled = size * scale;
4334 rescaled = std::round( rescaled );
4341 double x =
rescaleUom( point.x(), unit, props );
4342 double y =
rescaleUom( point.y(), unit, props );
4343 return QPointF( x, y );
4348 QVector<qreal> result;
4349 QVector<qreal>::const_iterator it = array.constBegin();
4350 for ( ; it != array.constEnd(); ++it )
4352 result.append(
rescaleUom( *it, unit, props ) );
4359 if ( !props.value( QStringLiteral(
"scaleMinDenom" ), QString() ).isEmpty() )
4361 QDomElement scaleMinDenomElem = doc.createElement( QStringLiteral(
"se:MinScaleDenominator" ) );
4362 scaleMinDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMinDenom" ) ).toDouble() ) ) );
4363 ruleElem.appendChild( scaleMinDenomElem );
4366 if ( !props.value( QStringLiteral(
"scaleMaxDenom" ), QString() ).isEmpty() )
4368 QDomElement scaleMaxDenomElem = doc.createElement( QStringLiteral(
"se:MaxScaleDenominator" ) );
4369 scaleMaxDenomElem.appendChild( doc.createTextNode(
qgsDoubleToString( props.value( QStringLiteral(
"scaleMaxDenom" ) ).toDouble() ) ) );
4370 ruleElem.appendChild( scaleMaxDenomElem );
4379 double parentScaleMinDenom = props.value( QStringLiteral(
"scaleMinDenom" ), QStringLiteral(
"0" ) ).toDouble( &ok );
4380 if ( !ok || parentScaleMinDenom <= 0 )
4381 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( mScaleMinDenom );
4383 props[ QStringLiteral(
"scaleMinDenom" )] = QString::number( std::max( parentScaleMinDenom, mScaleMinDenom ) );
4389 double parentScaleMaxDenom = props.value( QStringLiteral(
"scaleMaxDenom" ), QStringLiteral(
"0" ) ).toDouble( &ok );
4390 if ( !ok || parentScaleMaxDenom <= 0 )
4391 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( mScaleMaxDenom );
4393 props[ QStringLiteral(
"scaleMaxDenom" )] = QString::number( std::min( parentScaleMaxDenom, mScaleMaxDenom ) );
4401 if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/metre" ) )
4403 scale = 1.0 / 0.00028;
4405 else if ( uom == QLatin1String(
"http://www.opengeospatial.org/se/units/foot" ) )
4407 scale = 304.8 / 0.28;
4414 return size * scale;
4423 : mSymbolLayerIds( layerIds )
4436 void visitSymbol(
const QgsSymbol *symbol,
const QString &identifier, QVector<int> rootPath )
4440 QVector<int> indexPath = rootPath;
4441 indexPath.append( idx );
4443 if ( mSymbolLayerIds.contains(
QgsSymbolLayerId( mCurrentRuleKey + identifier, indexPath ) ) )
4445 mSymbolLayers.insert( sl );
4450 visitSymbol( subSymbol, identifier, indexPath );
4459 if ( symbolEntity->symbol() )
4461 visitSymbol( symbolEntity->symbol(), leaf.
identifier, {} );
4467 QString mCurrentRuleKey;
4468 const QSet<QgsSymbolLayerId> &mSymbolLayerIds;
4469 QSet<const QgsSymbolLayer *> mSymbolLayers;
4473 renderer->
accept( &visitor );
4474 return visitor.mSymbolLayers;