38 #include <QRegularExpression>
48 if ( style.contains( QStringLiteral(
"layers" ) ) )
50 parseLayers( style.value( QStringLiteral(
"layers" ) ).toList(), context );
54 mError = QObject::tr(
"Could not find layers list in JSON" );
69 std::unique_ptr< QgsMapBoxGlStyleConversionContext > tmpContext;
72 tmpContext = qgis::make_unique< QgsMapBoxGlStyleConversionContext >();
73 context = tmpContext.get();
76 QList<QgsVectorTileBasicRendererStyle> rendererStyles;
77 QList<QgsVectorTileBasicLabelingStyle> labelingStyles;
79 for (
const QVariant &layer : layers )
81 const QVariantMap jsonLayer = layer.toMap();
83 const QString layerType = jsonLayer.value( QStringLiteral(
"type" ) ).toString();
84 if ( layerType == QLatin1String(
"background" ) )
87 const QString styleId = jsonLayer.value( QStringLiteral(
"id" ) ).toString();
89 const QString layerName = jsonLayer.value( QStringLiteral(
"source-layer" ) ).toString();
91 const int minZoom = jsonLayer.value( QStringLiteral(
"minzoom" ), QStringLiteral(
"-1" ) ).toInt();
92 const int maxZoom = jsonLayer.value( QStringLiteral(
"maxzoom" ), QStringLiteral(
"-1" ) ).toInt();
94 const bool enabled = jsonLayer.value( QStringLiteral(
"visibility" ) ).toString() != QLatin1String(
"none" );
96 QString filterExpression;
97 if ( jsonLayer.contains( QStringLiteral(
"filter" ) ) )
99 filterExpression =
parseExpression( jsonLayer.value( QStringLiteral(
"filter" ) ).toList(), *context );
105 bool hasRendererStyle =
false;
106 bool hasLabelingStyle =
false;
107 if ( layerType == QLatin1String(
"fill" ) )
109 hasRendererStyle =
parseFillLayer( jsonLayer, rendererStyle, *context );
111 else if ( layerType == QLatin1String(
"line" ) )
113 hasRendererStyle =
parseLineLayer( jsonLayer, rendererStyle, *context );
115 else if ( layerType == QLatin1String(
"circle" ) )
119 else if ( layerType == QLatin1String(
"symbol" ) )
121 parseSymbolLayer( jsonLayer, rendererStyle, hasRendererStyle, labelingStyle, hasLabelingStyle, *context );
125 mWarnings << QObject::tr(
"%1: Skipping unknown layer type %2" ).arg( context->
layerId(), layerType );
130 if ( hasRendererStyle )
138 rendererStyles.append( rendererStyle );
141 if ( hasLabelingStyle )
149 labelingStyles.append( labelingStyle );
152 mWarnings.append( context->
warnings() );
156 mRenderer = qgis::make_unique< QgsVectorTileBasicRenderer >();
158 renderer->setStyles( rendererStyles );
160 mLabeling = qgis::make_unique< QgsVectorTileBasicLabeling >();
162 labeling->setStyles( labelingStyles );
167 if ( !jsonLayer.contains( QStringLiteral(
"paint" ) ) )
169 context.
pushWarning( QObject::tr(
"%1: Layer has no paint property, skipping" ).arg( jsonLayer.value( QStringLiteral(
"id" ) ).toString() ) );
173 const QVariantMap jsonPaint = jsonLayer.value( QStringLiteral(
"paint" ) ).toMap();
180 if ( jsonPaint.contains( QStringLiteral(
"fill-color" ) ) )
182 const QVariant jsonFillColor = jsonPaint.
value( QStringLiteral(
"fill-color" ) );
183 switch ( jsonFillColor.type() )
190 case QVariant::StringList:
194 case QVariant::String:
195 fillColor =
parseColor( jsonFillColor.toString(), context );
208 fillColor = QColor( 0, 0, 0 );
211 QColor fillOutlineColor;
212 if ( !jsonPaint.contains( QStringLiteral(
"fill-outline-color" ) ) )
215 if ( fillColor.isValid() )
216 fillOutlineColor = fillColor;
226 const QVariant jsonFillOutlineColor = jsonPaint.value( QStringLiteral(
"fill-outline-color" ) );
227 switch ( jsonFillOutlineColor.type() )
234 case QVariant::StringList:
238 case QVariant::String:
239 fillOutlineColor =
parseColor( jsonFillOutlineColor.toString(), context );
248 double fillOpacity = -1.0;
249 double rasterOpacity = -1.0;
250 if ( jsonPaint.contains( QStringLiteral(
"fill-opacity" ) ) )
252 const QVariant jsonFillOpacity = jsonPaint.value( QStringLiteral(
"fill-opacity" ) );
253 switch ( jsonFillOpacity.type() )
256 case QVariant::Double:
257 fillOpacity = jsonFillOpacity.toDouble();
258 rasterOpacity = fillOpacity;
264 context.
pushWarning( QObject::tr(
"%1: Could not set opacity of layer, opacity already defined in fill color" ).arg( context.
layerId() ) );
275 case QVariant::StringList:
278 context.
pushWarning( QObject::tr(
"%1: Could not set opacity of layer, opacity already defined in fill color" ).arg( context.
layerId() ) );
295 QPointF fillTranslate;
296 if ( jsonPaint.contains( QStringLiteral(
"fill-translate" ) ) )
298 const QVariant jsonFillTranslate = jsonPaint.value( QStringLiteral(
"fill-translate" ) );
299 switch ( jsonFillTranslate.type() )
307 case QVariant::StringList:
318 std::unique_ptr< QgsSymbol > symbol( qgis::make_unique< QgsFillSymbol >() );
320 Q_ASSERT( fillSymbol );
323 symbol->setOutputUnit( context.
targetUnit() );
326 if ( !fillTranslate.isNull() )
332 if ( jsonPaint.contains( QStringLiteral(
"fill-pattern" ) ) )
336 const QVariant fillPatternJson = jsonPaint.value( QStringLiteral(
"fill-pattern" ) );
339 fillColor = QColor();
340 fillOutlineColor = QColor();
347 QString spriteProperty, spriteSizeProperty;
348 const QString sprite =
retrieveSpriteAsBase64( fillPatternJson, context, spriteSize, spriteProperty, spriteSizeProperty );
349 if ( !sprite.isEmpty() )
354 rasterFill->
setWidth( spriteSize.width() );
358 if ( rasterOpacity >= 0 )
363 if ( !spriteProperty.isEmpty() )
370 symbol->appendSymbolLayer( rasterFill );
376 if ( fillOpacity != -1 )
378 symbol->setOpacity( fillOpacity );
381 if ( fillOutlineColor.isValid() )
390 if ( fillColor.isValid() )
406 if ( !jsonLayer.contains( QStringLiteral(
"paint" ) ) )
408 context.
pushWarning( QObject::tr(
"%1: Style has no paint property, skipping" ).arg( context.
layerId() ) );
412 const QVariantMap jsonPaint = jsonLayer.value( QStringLiteral(
"paint" ) ).toMap();
413 if ( jsonPaint.contains( QStringLiteral(
"line-pattern" ) ) )
415 context.
pushWarning( QObject::tr(
"%1: Skipping unsupported line-pattern property" ).arg( context.
layerId() ) );
423 if ( jsonPaint.contains( QStringLiteral(
"line-color" ) ) )
425 const QVariant jsonLineColor = jsonPaint.
value( QStringLiteral(
"line-color" ) );
426 switch ( jsonLineColor.type() )
434 case QVariant::StringList:
439 case QVariant::String:
440 lineColor =
parseColor( jsonLineColor.toString(), context );
451 lineColor = QColor( 0, 0, 0 );
455 double lineWidth = 1.0;
456 if ( jsonPaint.contains( QStringLiteral(
"line-width" ) ) )
458 const QVariant jsonLineWidth = jsonPaint.value( QStringLiteral(
"line-width" ) );
459 switch ( jsonLineWidth.type() )
462 case QVariant::Double:
472 case QVariant::StringList:
482 double lineOffset = 0.0;
483 if ( jsonPaint.contains( QStringLiteral(
"line-offset" ) ) )
485 const QVariant jsonLineOffset = jsonPaint.value( QStringLiteral(
"line-offset" ) );
486 switch ( jsonLineOffset.type() )
489 case QVariant::Double:
499 case QVariant::StringList:
509 double lineOpacity = -1.0;
510 if ( jsonPaint.contains( QStringLiteral(
"line-opacity" ) ) )
512 const QVariant jsonLineOpacity = jsonPaint.value( QStringLiteral(
"line-opacity" ) );
513 switch ( jsonLineOpacity.type() )
516 case QVariant::Double:
517 lineOpacity = jsonLineOpacity.toDouble();
523 context.
pushWarning( QObject::tr(
"%1: Could not set opacity of layer, opacity already defined in stroke color" ).arg( context.
layerId() ) );
532 case QVariant::StringList:
535 context.
pushWarning( QObject::tr(
"%1: Could not set opacity of layer, opacity already defined in stroke color" ).arg( context.
layerId() ) );
549 QVector< double > dashVector;
550 if ( jsonPaint.contains( QStringLiteral(
"line-dasharray" ) ) )
552 const QVariant jsonLineDashArray = jsonPaint.value( QStringLiteral(
"line-dasharray" ) );
553 switch ( jsonLineDashArray.type() )
558 const QVariantList dashSource = jsonLineDashArray.toMap().value( QStringLiteral(
"stops" ) ).toList().last().toList().value( 1 ).toList();
559 for (
const QVariant &v : dashSource )
567 case QVariant::StringList:
569 const QVariantList dashSource = jsonLineDashArray.toList();
570 for (
const QVariant &v : dashSource )
583 Qt::PenCapStyle penCapStyle = Qt::FlatCap;
584 Qt::PenJoinStyle penJoinStyle = Qt::MiterJoin;
585 if ( jsonLayer.contains( QStringLiteral(
"layout" ) ) )
587 const QVariantMap jsonLayout = jsonLayer.value( QStringLiteral(
"layout" ) ).toMap();
588 if ( jsonLayout.contains( QStringLiteral(
"line-cap" ) ) )
590 penCapStyle =
parseCapStyle( jsonLayout.value( QStringLiteral(
"line-cap" ) ).toString() );
592 if ( jsonLayout.contains( QStringLiteral(
"line-join" ) ) )
594 penJoinStyle =
parseJoinStyle( jsonLayout.value( QStringLiteral(
"line-join" ) ).toString() );
598 std::unique_ptr< QgsSymbol > symbol( qgis::make_unique< QgsLineSymbol >() );
600 Q_ASSERT( lineSymbol );
603 symbol->setOutputUnit( context.
targetUnit() );
611 if ( lineOpacity != -1 )
613 symbol->setOpacity( lineOpacity );
615 if ( lineColor.isValid() )
619 if ( lineWidth != -1 )
623 if ( !dashVector.empty() )
636 if ( !jsonLayer.contains( QStringLiteral(
"paint" ) ) )
638 context.
pushWarning( QObject::tr(
"%1: Style has no paint property, skipping" ).arg( context.
layerId() ) );
642 const QVariantMap jsonPaint = jsonLayer.value( QStringLiteral(
"paint" ) ).toMap();
646 QColor circleFillColor;
647 if ( jsonPaint.contains( QStringLiteral(
"circle-color" ) ) )
649 const QVariant jsonCircleColor = jsonPaint.
value( QStringLiteral(
"circle-color" ) );
650 switch ( jsonCircleColor.type() )
657 case QVariant::StringList:
661 case QVariant::String:
662 circleFillColor =
parseColor( jsonCircleColor.toString(), context );
673 circleFillColor = QColor( 0, 0, 0 );
677 double circleDiameter = 10.0;
678 if ( jsonPaint.contains( QStringLiteral(
"circle-radius" ) ) )
680 const QVariant jsonCircleRadius = jsonPaint.value( QStringLiteral(
"circle-radius" ) );
681 switch ( jsonCircleRadius.type() )
684 case QVariant::Double:
694 case QVariant::StringList:
704 double circleOpacity = -1.0;
705 if ( jsonPaint.contains( QStringLiteral(
"circle-opacity" ) ) )
707 const QVariant jsonCircleOpacity = jsonPaint.value( QStringLiteral(
"circle-opacity" ) );
708 switch ( jsonCircleOpacity.type() )
711 case QVariant::Double:
712 circleOpacity = jsonCircleOpacity.toDouble();
720 case QVariant::StringList:
729 if ( ( circleOpacity != -1 ) && circleFillColor.isValid() )
731 circleFillColor.setAlphaF( circleOpacity );
735 QColor circleStrokeColor;
736 if ( jsonPaint.contains( QStringLiteral(
"circle-stroke-color" ) ) )
738 const QVariant jsonCircleStrokeColor = jsonPaint.value( QStringLiteral(
"circle-stroke-color" ) );
739 switch ( jsonCircleStrokeColor.type() )
746 case QVariant::StringList:
750 case QVariant::String:
751 circleStrokeColor =
parseColor( jsonCircleStrokeColor.toString(), context );
761 double circleStrokeWidth = -1.0;
762 if ( jsonPaint.contains( QStringLiteral(
"circle-stroke-width" ) ) )
764 const QVariant circleStrokeWidthJson = jsonPaint.value( QStringLiteral(
"circle-stroke-width" ) );
765 switch ( circleStrokeWidthJson.type() )
768 case QVariant::Double:
773 circleStrokeWidth = -1.0;
778 case QVariant::StringList:
788 double circleStrokeOpacity = -1.0;
789 if ( jsonPaint.contains( QStringLiteral(
"circle-stroke-opacity" ) ) )
791 const QVariant jsonCircleStrokeOpacity = jsonPaint.value( QStringLiteral(
"circle-stroke-opacity" ) );
792 switch ( jsonCircleStrokeOpacity.type() )
795 case QVariant::Double:
796 circleStrokeOpacity = jsonCircleStrokeOpacity.toDouble();
804 case QVariant::StringList:
813 if ( ( circleStrokeOpacity != -1 ) && circleStrokeColor.isValid() )
815 circleStrokeColor.setAlphaF( circleStrokeOpacity );
819 QPointF circleTranslate;
820 if ( jsonPaint.contains( QStringLiteral(
"circle-translate" ) ) )
822 const QVariant jsonCircleTranslate = jsonPaint.value( QStringLiteral(
"circle-translate" ) );
823 switch ( jsonCircleTranslate.type() )
831 case QVariant::StringList:
842 std::unique_ptr< QgsSymbol > symbol( qgis::make_unique< QgsMarkerSymbol >() );
844 Q_ASSERT( markerSymbolLayer );
847 symbol->setOutputUnit( context.
targetUnit() );
848 symbol->setDataDefinedProperties( ddProperties );
850 if ( !circleTranslate.isNull() )
852 markerSymbolLayer->
setOffset( circleTranslate );
856 if ( circleFillColor.isValid() )
860 if ( circleDiameter != -1 )
862 markerSymbolLayer->
setSize( circleDiameter );
865 if ( circleStrokeColor.isValid() )
869 if ( circleStrokeWidth != -1 )
885 if ( !jsonLayer.contains( QStringLiteral(
"layout" ) ) )
887 context.
pushWarning( QObject::tr(
"%1: Style layer has no layout property, skipping" ).arg( context.
layerId() ) );
890 const QVariantMap jsonLayout = jsonLayer.value( QStringLiteral(
"layout" ) ).toMap();
891 if ( !jsonLayout.contains( QStringLiteral(
"text-field" ) ) )
897 if ( !jsonLayer.contains( QStringLiteral(
"paint" ) ) )
899 context.
pushWarning( QObject::tr(
"%1: Style layer has no paint property, skipping" ).arg( context.
layerId() ) );
902 const QVariantMap jsonPaint = jsonLayer.value( QStringLiteral(
"paint" ) ).toMap();
907 QString textSizeProperty;
908 if ( jsonLayout.contains( QStringLiteral(
"text-size" ) ) )
910 const QVariant jsonTextSize = jsonLayout.value( QStringLiteral(
"text-size" ) );
911 switch ( jsonTextSize.type() )
914 case QVariant::Double:
925 case QVariant::StringList:
935 if ( !textSizeProperty.isEmpty() )
942 constexpr
double EM_TO_CHARS = 2.0;
944 double textMaxWidth = -1;
945 if ( jsonLayout.contains( QStringLiteral(
"text-max-width" ) ) )
947 const QVariant jsonTextMaxWidth = jsonLayout.value( QStringLiteral(
"text-max-width" ) );
948 switch ( jsonTextMaxWidth.type() )
951 case QVariant::Double:
952 textMaxWidth = jsonTextMaxWidth.toDouble() * EM_TO_CHARS;
960 case QVariant::StringList:
972 textMaxWidth = 10 * EM_TO_CHARS;
975 double textLetterSpacing = -1;
976 if ( jsonLayout.contains( QStringLiteral(
"text-letter-spacing" ) ) )
978 const QVariant jsonTextLetterSpacing = jsonLayout.value( QStringLiteral(
"text-letter-spacing" ) );
979 switch ( jsonTextLetterSpacing.type() )
982 case QVariant::Double:
983 textLetterSpacing = jsonTextLetterSpacing.toDouble();
991 case QVariant::StringList:
1002 bool foundFont =
false;
1004 if ( jsonLayout.contains( QStringLiteral(
"text-font" ) ) )
1006 auto splitFontFamily = [](
const QString & fontName, QString & family, QString & style ) ->
bool
1008 const QStringList textFontParts = fontName.split(
' ' );
1009 for (
int i = 1; i < textFontParts.size(); ++i )
1011 const QString candidateFontName = textFontParts.mid( 0, i ).join(
' ' );
1012 const QString candidateFontStyle = textFontParts.mid( i ).join(
' ' );
1015 family = candidateFontName;
1016 style = candidateFontStyle;
1021 if ( QFontDatabase().hasFamily( fontName ) )
1031 const QVariant jsonTextFont = jsonLayout.value( QStringLiteral(
"text-font" ) );
1032 if ( jsonTextFont.type() != QVariant::List && jsonTextFont.type() != QVariant::StringList && jsonTextFont.type() != QVariant::String
1033 && jsonTextFont.type() != QVariant::Map )
1039 switch ( jsonTextFont.type() )
1041 case QVariant::List:
1042 case QVariant::StringList:
1043 fontName = jsonTextFont.toList().value( 0 ).toString();
1046 case QVariant::String:
1047 fontName = jsonTextFont.toString();
1052 QString familyCaseString = QStringLiteral(
"CASE " );
1053 QString styleCaseString = QStringLiteral(
"CASE " );
1056 const QVariantList stops = jsonTextFont.toMap().value( QStringLiteral(
"stops" ) ).toList();
1059 for (
int i = 0; i < stops.length() - 1; ++i )
1062 const QVariant bz = stops.value( i ).toList().value( 0 );
1063 const QString bv = stops.value( i ).toList().value( 1 ).type() == QVariant::String ? stops.value( i ).toList().value( 1 ).toString() : stops.value( i ).toList().value( 1 ).toList().value( 0 ).toString();
1064 if ( bz.type() == QVariant::List || bz.type() == QVariant::StringList )
1066 context.
pushWarning( QObject::tr(
"%1: Expressions in interpolation function are not supported, skipping." ).arg( context.
layerId() ) );
1072 const QVariant tz = stops.value( i + 1 ).toList().value( 0 );
1073 if ( tz.type() == QVariant::List || tz.type() == QVariant::StringList )
1075 context.
pushWarning( QObject::tr(
"%1: Expressions in interpolation function are not supported, skipping." ).arg( context.
layerId() ) );
1080 if ( splitFontFamily( bv, fontFamily, fontStyle ) )
1082 familyCaseString += QStringLiteral(
"WHEN @vector_tile_zoom > %1 AND @vector_tile_zoom <= %2 "
1083 "THEN %3 " ).arg( bz.toString(),
1086 styleCaseString += QStringLiteral(
"WHEN @vector_tile_zoom > %1 AND @vector_tile_zoom <= %2 "
1087 "THEN %3 " ).arg( bz.toString(),
1093 context.
pushWarning( QObject::tr(
"%1: Referenced font %2 is not available on system" ).arg( context.
layerId(), bv ) );
1099 const QString bv = stops.constLast().toList().value( 1 ).type() == QVariant::String ? stops.constLast().toList().value( 1 ).toString() : stops.constLast().toList().value( 1 ).toList().value( 0 ).toString();
1100 if ( splitFontFamily( bv, fontFamily, fontStyle ) )
1107 context.
pushWarning( QObject::tr(
"%1: Referenced font %2 is not available on system" ).arg( context.
layerId(), bv ) );
1114 fontName = fontFamily;
1125 if ( splitFontFamily( fontName, fontFamily, fontStyle ) )
1127 textFont = QFont( fontFamily );
1128 if ( !fontStyle.isEmpty() )
1129 textFont.setStyleName( fontStyle );
1139 fontName = QStringLiteral(
"Open Sans" );
1140 textFont = QFont( fontName );
1141 textFont.setStyleName( QStringLiteral(
"Regular" ) );
1146 fontName = QStringLiteral(
"Arial Unicode MS" );
1147 textFont = QFont( fontName );
1148 textFont.setStyleName( QStringLiteral(
"Regular" ) );
1153 fontName = QStringLiteral(
"Open Sans, Arial Unicode MS" );
1156 if ( !foundFont && !fontName.isEmpty() )
1158 context.
pushWarning( QObject::tr(
"%1: Referenced font %2 is not available on system" ).arg( context.
layerId(), fontName ) );
1163 if ( jsonPaint.contains( QStringLiteral(
"text-color" ) ) )
1165 const QVariant jsonTextColor = jsonPaint.value( QStringLiteral(
"text-color" ) );
1166 switch ( jsonTextColor.type() )
1172 case QVariant::List:
1173 case QVariant::StringList:
1177 case QVariant::String:
1178 textColor =
parseColor( jsonTextColor.toString(), context );
1189 textColor = QColor( 0, 0, 0 );
1194 if ( jsonPaint.contains( QStringLiteral(
"text-halo-color" ) ) )
1196 const QVariant jsonBufferColor = jsonPaint.value( QStringLiteral(
"text-halo-color" ) );
1197 switch ( jsonBufferColor.type() )
1203 case QVariant::List:
1204 case QVariant::StringList:
1208 case QVariant::String:
1209 bufferColor =
parseColor( jsonBufferColor.toString(), context );
1218 double bufferSize = 0.0;
1222 constexpr
double BUFFER_SIZE_SCALE = 2.0;
1223 if ( jsonPaint.contains( QStringLiteral(
"text-halo-width" ) ) )
1225 const QVariant jsonHaloWidth = jsonPaint.value( QStringLiteral(
"text-halo-width" ) );
1226 switch ( jsonHaloWidth.type() )
1229 case QVariant::Double:
1238 case QVariant::List:
1239 case QVariant::StringList:
1250 double haloBlurSize = 0;
1251 if ( jsonPaint.contains( QStringLiteral(
"text-halo-blur" ) ) )
1253 const QVariant jsonTextHaloBlur = jsonPaint.value( QStringLiteral(
"text-halo-blur" ) );
1254 switch ( jsonTextHaloBlur.type() )
1257 case QVariant::Double:
1271 if ( textColor.isValid() )
1273 if ( textSize >= 0 )
1277 if ( textLetterSpacing > 0 )
1279 QFont f = format.
font();
1280 f.setLetterSpacing( QFont::AbsoluteSpacing, textLetterSpacing );
1284 if ( bufferSize > 0 )
1291 if ( haloBlurSize > 0 )
1307 if ( textMaxWidth > 0 )
1314 auto processLabelField = [](
const QString & string,
bool & isExpression )->QString
1318 const QRegularExpression singleFieldRx( QStringLiteral(
"^{([^}]+)}$" ) );
1319 QRegularExpressionMatch match = singleFieldRx.match(
string );
1320 if ( match.hasMatch() )
1322 isExpression =
false;
1323 return match.captured( 1 );
1326 const QRegularExpression multiFieldRx( QStringLiteral(
"(?={[^}]+})" ) );
1327 const QStringList parts =
string.split( multiFieldRx );
1328 if ( parts.size() > 1 )
1330 isExpression =
true;
1333 for (
const QString &part : parts )
1335 if ( part.isEmpty() )
1339 const QStringList split = part.split(
'}' );
1341 if ( !split.at( 1 ).isEmpty() )
1344 return QStringLiteral(
"concat(%1)" ).arg( res.join(
',' ) );
1348 isExpression =
false;
1353 if ( jsonLayout.contains( QStringLiteral(
"text-field" ) ) )
1355 const QVariant jsonTextField = jsonLayout.value( QStringLiteral(
"text-field" ) );
1356 switch ( jsonTextField.type() )
1358 case QVariant::String:
1360 labelSettings.
fieldName = processLabelField( jsonTextField.toString(), labelSettings.
isExpression );
1364 case QVariant::List:
1365 case QVariant::StringList:
1367 const QVariantList textFieldList = jsonTextField.toList();
1375 if ( textFieldList.size() > 2 && textFieldList.at( 0 ).toString() == QLatin1String(
"format" ) )
1378 for (
int i = 1; i < textFieldList.size(); ++i )
1380 bool isExpression =
false;
1381 const QString part = processLabelField( textFieldList.at( i ).toString(), isExpression );
1382 if ( !isExpression )
1389 labelSettings.
fieldName = QStringLiteral(
"concat(%1)" ).arg( parts.join(
',' ) );
1410 if ( jsonLayout.contains( QStringLiteral(
"text-transform" ) ) )
1412 const QString textTransform = jsonLayout.value( QStringLiteral(
"text-transform" ) ).toString();
1413 if ( textTransform == QLatin1String(
"uppercase" ) )
1417 else if ( textTransform == QLatin1String(
"lowercase" ) )
1426 if ( jsonLayout.contains( QStringLiteral(
"symbol-placement" ) ) )
1428 const QString symbolPlacement = jsonLayout.value( QStringLiteral(
"symbol-placement" ) ).toString();
1429 if ( symbolPlacement == QLatin1String(
"line" ) )
1435 if ( jsonLayout.contains( QStringLiteral(
"text-rotation-alignment" ) ) )
1437 const QString textRotationAlignment = jsonLayout.value( QStringLiteral(
"text-rotation-alignment" ) ).toString();
1438 if ( textRotationAlignment == QLatin1String(
"viewport" ) )
1447 QString textOffsetProperty;
1448 if ( jsonLayout.contains( QStringLiteral(
"text-offset" ) ) )
1450 const QVariant jsonTextOffset = jsonLayout.value( QStringLiteral(
"text-offset" ) );
1453 switch ( jsonTextOffset.type() )
1456 textOffsetProperty =
parseInterpolatePointByZoom( jsonTextOffset.toMap(), context, textSizeProperty.isEmpty() ? textSize : 1.0, &textOffset );
1457 if ( textSizeProperty.isEmpty() )
1468 case QVariant::List:
1469 case QVariant::StringList:
1470 textOffset = QPointF( jsonTextOffset.toList().value( 0 ).toDouble() * textSize,
1471 jsonTextOffset.toList().value( 1 ).toDouble() * textSize );
1479 if ( !textOffset.isNull() )
1482 labelSettings.
dist = std::abs( textOffset.y() ) - textSize;
1484 if ( !textSizeProperty.isEmpty() && textOffsetProperty.isEmpty() )
1491 if ( textOffset.isNull() )
1499 if ( jsonLayout.contains( QStringLiteral(
"text-justify" ) ) )
1501 const QVariant jsonTextJustify = jsonLayout.value( QStringLiteral(
"text-justify" ) );
1504 QString textAlign = QStringLiteral(
"center" );
1506 const QVariantMap conversionMap
1508 { QStringLiteral(
"left" ), QStringLiteral(
"left" ) },
1509 { QStringLiteral(
"center" ), QStringLiteral(
"center" ) },
1510 { QStringLiteral(
"right" ), QStringLiteral(
"right" ) },
1511 { QStringLiteral(
"auto" ), QStringLiteral(
"follow" ) }
1514 switch ( jsonTextJustify.type() )
1516 case QVariant::String:
1517 textAlign = jsonTextJustify.toString();
1520 case QVariant::List:
1533 if ( textAlign == QLatin1String(
"left" ) )
1535 else if ( textAlign == QLatin1String(
"right" ) )
1537 else if ( textAlign == QLatin1String(
"center" ) )
1539 else if ( textAlign == QLatin1String(
"follow" ) )
1549 if ( jsonLayout.contains( QStringLiteral(
"text-anchor" ) ) )
1551 const QVariant jsonTextAnchor = jsonLayout.value( QStringLiteral(
"text-anchor" ) );
1554 const QVariantMap conversionMap
1556 { QStringLiteral(
"center" ), 4 },
1557 { QStringLiteral(
"left" ), 5 },
1558 { QStringLiteral(
"right" ), 3 },
1559 { QStringLiteral(
"top" ), 7 },
1560 { QStringLiteral(
"bottom" ), 1 },
1561 { QStringLiteral(
"top-left" ), 8 },
1562 { QStringLiteral(
"top-right" ), 6 },
1563 { QStringLiteral(
"bottom-left" ), 2 },
1564 { QStringLiteral(
"bottom-right" ), 0 },
1567 switch ( jsonTextAnchor.type() )
1569 case QVariant::String:
1570 textAnchor = jsonTextAnchor.toString();
1573 case QVariant::List:
1586 if ( textAnchor == QLatin1String(
"center" ) )
1588 else if ( textAnchor == QLatin1String(
"left" ) )
1590 else if ( textAnchor == QLatin1String(
"right" ) )
1592 else if ( textAnchor == QLatin1String(
"top" ) )
1594 else if ( textAnchor == QLatin1String(
"bottom" ) )
1596 else if ( textAnchor == QLatin1String(
"top-left" ) )
1598 else if ( textAnchor == QLatin1String(
"top-right" ) )
1600 else if ( textAnchor == QLatin1String(
"bottom-left" ) )
1602 else if ( textAnchor == QLatin1String(
"bottom-right" ) )
1607 if ( jsonLayout.contains( QStringLiteral(
"text-offset" ) ) )
1609 const QVariant jsonTextOffset = jsonLayout.value( QStringLiteral(
"text-offset" ) );
1612 switch ( jsonTextOffset.type() )
1618 case QVariant::List:
1619 case QVariant::StringList:
1620 textOffset = QPointF( jsonTextOffset.toList().value( 0 ).toDouble() * textSize,
1621 jsonTextOffset.toList().value( 1 ).toDouble() * textSize );
1629 if ( !textOffset.isNull() )
1632 labelSettings.
xOffset = textOffset.x();
1633 labelSettings.
yOffset = textOffset.y();
1638 if ( jsonLayout.contains( QStringLiteral(
"icon-image" ) ) &&
1642 QString spriteProperty, spriteSizeProperty;
1643 const QString sprite =
retrieveSpriteAsBase64( jsonLayout.value( QStringLiteral(
"icon-image" ) ), context, spriteSize, spriteProperty, spriteSizeProperty );
1644 if ( !sprite.isEmpty() )
1647 markerLayer->
setPath( sprite );
1648 markerLayer->
setSize( spriteSize.width() );
1651 if ( !spriteProperty.isEmpty() )
1663 backgroundSettings.
setSize( spriteSize );
1671 if ( textSize >= 0 )
1694 if ( !jsonLayer.contains( QStringLiteral(
"layout" ) ) )
1696 context.
pushWarning( QObject::tr(
"%1: Style layer has no layout property, skipping" ).arg( context.
layerId() ) );
1699 const QVariantMap jsonLayout = jsonLayer.value( QStringLiteral(
"layout" ) ).toMap();
1701 if ( jsonLayout.value( QStringLiteral(
"symbol-placement" ) ).toString() == QLatin1String(
"line" ) && !jsonLayout.contains( QStringLiteral(
"text-field" ) ) )
1705 double spacing = -1.0;
1706 if ( jsonLayout.contains( QStringLiteral(
"symbol-spacing" ) ) )
1708 const QVariant jsonSpacing = jsonLayout.
value( QStringLiteral(
"symbol-spacing" ) );
1709 switch ( jsonSpacing.type() )
1712 case QVariant::Double:
1720 case QVariant::List:
1721 case QVariant::StringList:
1736 bool rotateMarkers =
true;
1737 if ( jsonLayout.contains( QStringLiteral(
"icon-rotation-alignment" ) ) )
1739 const QString alignment = jsonLayout.value( QStringLiteral(
"icon-rotation-alignment" ) ).toString();
1740 if ( alignment == QLatin1String(
"map" ) || alignment == QLatin1String(
"auto" ) )
1742 rotateMarkers =
true;
1744 else if ( alignment == QLatin1String(
"viewport" ) )
1746 rotateMarkers =
false;
1751 double rotation = 0.0;
1752 if ( jsonLayout.contains( QStringLiteral(
"icon-rotate" ) ) )
1754 const QVariant jsonIconRotate = jsonLayout.
value( QStringLiteral(
"icon-rotate" ) );
1755 switch ( jsonIconRotate.type() )
1758 case QVariant::Double:
1759 rotation = jsonIconRotate.toDouble();
1766 case QVariant::List:
1767 case QVariant::StringList:
1788 QString spriteProperty, spriteSizeProperty;
1789 const QString sprite =
retrieveSpriteAsBase64( jsonLayout.value( QStringLiteral(
"icon-image" ) ), context, spriteSize, spriteProperty, spriteSizeProperty );
1790 if ( !sprite.isNull() )
1792 markerLayer->
setPath( sprite );
1793 markerLayer->
setSize( spriteSize.width() );
1796 if ( !spriteProperty.isEmpty() )
1803 if ( jsonLayout.contains( QStringLiteral(
"icon-size" ) ) )
1805 const QVariant jsonIconSize = jsonLayout.value( QStringLiteral(
"icon-size" ) );
1808 switch ( jsonIconSize.type() )
1811 case QVariant::Double:
1813 size = jsonIconSize.toDouble();
1814 if ( !spriteSizeProperty.isEmpty() )
1817 QgsProperty::fromExpression( QStringLiteral(
"with_variable('marker_size',%1,%2*@marker_size)" ).arg( spriteSizeProperty ).arg( size ) ) );
1826 case QVariant::List:
1827 case QVariant::StringList:
1832 markerLayer->
setSize( size * spriteSize.width() );
1835 if ( !spriteSizeProperty.isEmpty() )
1852 std::unique_ptr< QgsSymbol > symbol = qgis::make_unique< QgsLineSymbol >(
QgsSymbolLayerList() << lineSymbol );
1855 symbol->setOutputUnit( context.
targetUnit() );
1859 rendererStyle.
setSymbol( symbol.release() );
1862 else if ( jsonLayout.contains( QStringLiteral(
"icon-image" ) ) )
1864 const QVariantMap jsonPaint = jsonLayer.value( QStringLiteral(
"paint" ) ).toMap();
1867 QString spriteProperty, spriteSizeProperty;
1868 const QString sprite =
retrieveSpriteAsBase64( jsonLayout.value( QStringLiteral(
"icon-image" ) ), context, spriteSize, spriteProperty, spriteSizeProperty );
1869 if ( !sprite.isEmpty() )
1872 rasterMarker->
setPath( sprite );
1873 rasterMarker->
setSize( spriteSize.width() );
1877 if ( !spriteProperty.isEmpty() )
1883 if ( jsonLayout.contains( QStringLiteral(
"icon-size" ) ) )
1885 const QVariant jsonIconSize = jsonLayout.value( QStringLiteral(
"icon-size" ) );
1888 switch ( jsonIconSize.type() )
1891 case QVariant::Double:
1893 size = jsonIconSize.toDouble();
1894 if ( !spriteSizeProperty.isEmpty() )
1897 QgsProperty::fromExpression( QStringLiteral(
"with_variable('marker_size',%1,%2*@marker_size)" ).arg( spriteSizeProperty ).arg( size ) ) );
1906 case QVariant::List:
1907 case QVariant::StringList:
1912 rasterMarker->
setSize( size * spriteSize.width() );
1915 if ( !spriteSizeProperty.isEmpty() )
1928 double rotation = 0.0;
1929 if ( jsonLayout.contains( QStringLiteral(
"icon-rotate" ) ) )
1931 const QVariant jsonIconRotate = jsonLayout.value( QStringLiteral(
"icon-rotate" ) );
1932 switch ( jsonIconRotate.type() )
1935 case QVariant::Double:
1936 rotation = jsonIconRotate.toDouble();
1943 case QVariant::List:
1944 case QVariant::StringList:
1954 double iconOpacity = -1.0;
1955 if ( jsonPaint.contains( QStringLiteral(
"icon-opacity" ) ) )
1957 const QVariant jsonIconOpacity = jsonPaint.value( QStringLiteral(
"icon-opacity" ) );
1958 switch ( jsonIconOpacity.type() )
1961 case QVariant::Double:
1962 iconOpacity = jsonIconOpacity.toDouble();
1969 case QVariant::List:
1970 case QVariant::StringList:
1981 rasterMarker->
setAngle( rotation );
1982 if ( iconOpacity >= 0 )
1986 rendererStyle.
setSymbol( markerSymbol );
1997 const double base = json.
value( QStringLiteral(
"base" ), QStringLiteral(
"1" ) ).toDouble();
1998 const QVariantList stops = json.value( QStringLiteral(
"stops" ) ).toList();
1999 if ( stops.empty() )
2002 QString caseString = QStringLiteral(
"CASE " );
2004 for (
int i = 0; i < stops.length() - 1; ++i )
2007 const QString bz = stops.at( i ).toList().value( 0 ).toString();
2009 const QString tz = stops.at( i + 1 ).toList().value( 0 ).toString();
2011 const QColor bottomColor =
parseColor( stops.at( i ).toList().value( 1 ), context );
2012 const QColor topColor =
parseColor( stops.at( i + 1 ).toList().value( 1 ), context );
2025 caseString += QStringLiteral(
"WHEN @vector_tile_zoom >= %1 AND @vector_tile_zoom < %2 THEN color_hsla("
2026 "%3, %4, %5, %6) " ).arg( bz, tz,
2034 const QString tz = stops.last().toList().value( 0 ).toString();
2035 const QColor topColor =
parseColor( stops.last().toList().value( 1 ), context );
2042 caseString += QStringLiteral(
"WHEN @vector_tile_zoom >= %1 THEN color_hsla(%2, %3, %4, %5) "
2043 "ELSE color_hsla(%2, %3, %4, %5) END" ).arg( tz )
2044 .arg( tcHue ).arg( tcSat ).arg( tcLight ).arg( tcAlpha );
2047 if ( !stops.empty() && defaultColor )
2048 *defaultColor =
parseColor( stops.value( 0 ).toList().value( 1 ).toString(), context );
2055 const double base = json.
value( QStringLiteral(
"base" ), QStringLiteral(
"1" ) ).toDouble();
2056 const QVariantList stops = json.value( QStringLiteral(
"stops" ) ).toList();
2057 if ( stops.empty() )
2060 QString scaleExpression;
2061 if ( stops.size() <= 2 )
2064 stops.last().toList().value( 0 ).toDouble(),
2065 stops.value( 0 ).toList().value( 1 ).toDouble(),
2066 stops.last().toList().value( 1 ).toDouble(), base, multiplier );
2070 scaleExpression =
parseStops( base, stops, multiplier, context );
2073 if ( !stops.empty() && defaultNumber )
2074 *defaultNumber = stops.value( 0 ).toList().value( 1 ).toDouble() * multiplier;
2081 const double base = json.
value( QStringLiteral(
"base" ), QStringLiteral(
"1" ) ).toDouble();
2082 const QVariantList stops = json.value( QStringLiteral(
"stops" ) ).toList();
2083 if ( stops.empty() )
2086 QString scaleExpression;
2087 if ( stops.length() <= 2 )
2089 scaleExpression = QStringLiteral(
"set_color_part(@symbol_color, 'alpha', %1)" )
2091 stops.last().toList().value( 0 ).toDouble(),
2092 stops.value( 0 ).toList().value( 1 ).toDouble() * maxOpacity,
2093 stops.last().toList().value( 1 ).toDouble() * maxOpacity, base ) );
2104 QString caseString = QStringLiteral(
"CASE WHEN @vector_tile_zoom < %1 THEN set_color_part(@symbol_color, 'alpha', %2)" )
2105 .arg( stops.value( 0 ).toList().value( 0 ).toString() )
2106 .arg( stops.value( 0 ).toList().value( 1 ).toDouble() * maxOpacity );
2108 for (
int i = 0; i < stops.size() - 1; ++i )
2110 caseString += QStringLiteral(
" WHEN @vector_tile_zoom >= %1 AND @vector_tile_zoom < %2 "
2111 "THEN set_color_part(@symbol_color, 'alpha', %3)" )
2112 .arg( stops.value( i ).toList().value( 0 ).toString(),
2113 stops.value( i + 1 ).toList().value( 0 ).toString(),
2115 stops.value( i + 1 ).toList().value( 0 ).toDouble(),
2116 stops.value( i ).toList().value( 1 ).toDouble() * maxOpacity,
2117 stops.value( i + 1 ).toList().value( 1 ).toDouble() * maxOpacity, base ) );
2120 caseString += QStringLiteral(
" WHEN @vector_tile_zoom >= %1 "
2121 "THEN set_color_part(@symbol_color, 'alpha', %2) END" )
2122 .arg( stops.last().toList().value( 0 ).toString() )
2123 .arg( stops.last().toList().value( 1 ).toDouble() * maxOpacity );
2129 const double base = json.
value( QStringLiteral(
"base" ), QStringLiteral(
"1" ) ).toDouble();
2130 const QVariantList stops = json.value( QStringLiteral(
"stops" ) ).toList();
2131 if ( stops.empty() )
2134 QString scaleExpression;
2135 if ( stops.size() <= 2 )
2137 scaleExpression = QStringLiteral(
"array(%1,%2)" ).arg(
interpolateExpression( stops.value( 0 ).toList().value( 0 ).toDouble(),
2138 stops.last().toList().value( 0 ).toDouble(),
2139 stops.value( 0 ).toList().value( 1 ).toList().value( 0 ).toDouble(),
2140 stops.last().toList().value( 1 ).toList().value( 0 ).toDouble(), base, multiplier ),
2142 stops.last().toList().value( 0 ).toDouble(),
2143 stops.value( 0 ).toList().value( 1 ).toList().value( 1 ).toDouble(),
2144 stops.last().toList().value( 1 ).toList().value( 1 ).toDouble(), base, multiplier )
2149 scaleExpression =
parsePointStops( base, stops, context, multiplier );
2152 if ( !stops.empty() && defaultPoint )
2153 *defaultPoint = QPointF( stops.value( 0 ).toList().value( 1 ).toList().value( 0 ).toDouble() * multiplier,
2154 stops.value( 0 ).toList().value( 1 ).toList().value( 1 ).toDouble() * multiplier );
2160 const QVariantMap &conversionMap, QString *defaultString )
2162 const QVariantList stops = json.
value( QStringLiteral(
"stops" ) ).toList();
2163 if ( stops.empty() )
2166 QString scaleExpression =
parseStringStops( stops, context, conversionMap, defaultString );
2173 QString caseString = QStringLiteral(
"CASE " );
2175 for (
int i = 0; i < stops.length() - 1; ++i )
2178 const QVariant bz = stops.value( i ).toList().value( 0 );
2179 const QVariant bv = stops.value( i ).toList().value( 1 );
2180 if ( bv.type() != QVariant::List && bv.type() != QVariant::StringList )
2187 const QVariant tz = stops.value( i + 1 ).toList().value( 0 );
2188 const QVariant tv = stops.value( i + 1 ).toList().value( 1 );
2189 if ( tv.type() != QVariant::List && tv.type() != QVariant::StringList )
2195 caseString += QStringLiteral(
"WHEN @vector_tile_zoom > %1 AND @vector_tile_zoom <= %2 "
2196 "THEN array(%3,%4)" ).arg( bz.toString(),
2198 interpolateExpression( bz.toDouble(), tz.toDouble(), bv.toList().value( 0 ).toDouble(), tv.toList().value( 0 ).toDouble(), base, multiplier ),
2199 interpolateExpression( bz.toDouble(), tz.toDouble(), bv.toList().value( 1 ).toDouble(), tv.toList().value( 1 ).toDouble(), base, multiplier ) );
2201 caseString += QLatin1String(
"END" );
2207 QString caseString = QStringLiteral(
"CASE " );
2209 for (
int i = 0; i < stops.length() - 1; ++i )
2212 const QVariant bz = stops.value( i ).toList().value( 0 );
2213 const QVariant bv = stops.value( i ).toList().value( 1 );
2214 if ( bz.type() == QVariant::List || bz.type() == QVariant::StringList )
2216 context.
pushWarning( QObject::tr(
"%1: Expressions in interpolation function are not supported, skipping." ).arg( context.
layerId() ) );
2221 const QVariant tz = stops.value( i + 1 ).toList().value( 0 );
2222 const QVariant tv = stops.value( i + 1 ).toList().value( 1 );
2223 if ( tz.type() == QVariant::List || tz.type() == QVariant::StringList )
2225 context.
pushWarning( QObject::tr(
"%1: Expressions in interpolation function are not supported, skipping." ).arg( context.
layerId() ) );
2229 caseString += QStringLiteral(
"WHEN @vector_tile_zoom > %1 AND @vector_tile_zoom <= %2 "
2230 "THEN %3 " ).arg( bz.toString(),
2232 interpolateExpression( bz.toDouble(), tz.toDouble(), bv.toDouble(), tv.toDouble(), base, multiplier ) );
2235 const QVariant z = stops.last().toList().value( 0 );
2236 const QVariant v = stops.last().toList().value( 1 );
2237 caseString += QStringLiteral(
"WHEN @vector_tile_zoom > %1 "
2238 "THEN %2 END" ).arg( z.toString() ).arg( v.toDouble() * multiplier );
2244 QString caseString = QStringLiteral(
"CASE " );
2246 for (
int i = 0; i < stops.length() - 1; ++i )
2249 const QVariant bz = stops.value( i ).toList().value( 0 );
2250 const QString bv = stops.value( i ).toList().value( 1 ).toString();
2251 if ( bz.type() == QVariant::List || bz.type() == QVariant::StringList )
2253 context.
pushWarning( QObject::tr(
"%1: Expressions in interpolation function are not supported, skipping." ).arg( context.
layerId() ) );
2258 const QVariant tz = stops.value( i + 1 ).toList().value( 0 );
2259 if ( tz.type() == QVariant::List || tz.type() == QVariant::StringList )
2261 context.
pushWarning( QObject::tr(
"%1: Expressions in interpolation function are not supported, skipping." ).arg( context.
layerId() ) );
2265 caseString += QStringLiteral(
"WHEN @vector_tile_zoom > %1 AND @vector_tile_zoom <= %2 "
2266 "THEN %3 " ).arg( bz.toString(),
2270 caseString += QStringLiteral(
"ELSE %1 END" ).arg(
QgsExpression::quotedValue( conversionMap.value( stops.constLast().toList().value( 1 ).toString(),
2271 stops.constLast().toList().value( 1 ) ) ) );
2272 if ( defaultString )
2273 *defaultString = stops.constLast().toList().value( 1 ).toString();
2279 const QString method = json.
value( 0 ).toString();
2280 if ( method == QLatin1String(
"interpolate" ) )
2284 else if ( method == QLatin1String(
"match" ) )
2286 return parseMatchList( json, type, context, multiplier, maxOpacity, defaultColor, defaultNumber );
2290 context.
pushWarning( QObject::tr(
"%1: Could not interpret value list with method %2" ).arg( context.
layerId(), method ) );
2297 const QString attribute =
parseExpression( json.value( 1 ).toList(), context );
2298 if ( attribute.isEmpty() )
2300 context.
pushWarning( QObject::tr(
"%1: Could not interpret match list" ).arg( context.
layerId() ) );
2304 QString caseString = QStringLiteral(
"CASE " );
2306 for (
int i = 2; i < json.length() - 1; i += 2 )
2308 const QVariantList keys = json.value( i ).toList();
2310 QStringList matchString;
2311 for (
const QVariant &key : keys )
2316 const QVariant value = json.value( i + 1 );
2318 QString valueString;
2323 const QColor color =
parseColor( value, context );
2330 const double v = value.toDouble() * multiplier;
2331 valueString = QString::number( v );
2337 const double v = value.toDouble() * maxOpacity;
2338 valueString = QString::number( v );
2344 valueString = QStringLiteral(
"array(%1,%2)" ).arg( value.toList().value( 0 ).toDouble() * multiplier,
2345 value.toList().value( 0 ).toDouble() * multiplier );
2351 caseString += QStringLiteral(
"WHEN %1 IN (%2) THEN %3 " ).arg( attribute,
2352 matchString.join(
',' ), valueString );
2361 const QColor color =
parseColor( json.constLast(), context );
2363 *defaultColor = color;
2371 const double v = json.constLast().toDouble() * multiplier;
2372 if ( defaultNumber )
2374 elseValue = QString::number( v );
2380 const double v = json.constLast().toDouble() * maxOpacity;
2381 if ( defaultNumber )
2383 elseValue = QString::number( v );
2389 elseValue = QStringLiteral(
"array(%1,%2)" ).arg( json.constLast().toList().value( 0 ).toDouble() * multiplier,
2390 json.constLast().toList().value( 0 ).toDouble() * multiplier );
2396 caseString += QStringLiteral(
"ELSE %1 END" ).arg( elseValue );
2402 if ( json.value( 0 ).toString() != QLatin1String(
"interpolate" ) )
2404 context.
pushWarning( QObject::tr(
"%1: Could not interpret value list" ).arg( context.
layerId() ) );
2409 const QString technique = json.value( 1 ).toList().value( 0 ).toString();
2410 if ( technique == QLatin1String(
"linear" ) )
2412 else if ( technique == QLatin1String(
"exponential" ) )
2413 base = json.value( 1 ).toList(). value( 1 ).toDouble();
2414 else if ( technique == QLatin1String(
"cubic-bezier" ) )
2416 context.
pushWarning( QObject::tr(
"%1: Cubic-bezier interpolation is not supported, linear used instead." ).arg( context.
layerId() ) );
2421 context.
pushWarning( QObject::tr(
"%1: Skipping not implemented interpolation method %2" ).arg( context.
layerId(), technique ) );
2425 if ( json.value( 2 ).toList().value( 0 ).toString() != QLatin1String(
"zoom" ) )
2427 context.
pushWarning( QObject::tr(
"%1: Skipping not implemented interpolation input %2" ).arg( context.
layerId(), json.value( 2 ).toString() ) );
2433 for (
int i = 3; i < json.length(); i += 2 )
2435 stops.push_back( QVariantList() << json.value( i ).toString() << json.value( i + 1 ).toString() );
2439 props.insert( QStringLiteral(
"stops" ), stops );
2440 props.insert( QStringLiteral(
"base" ), base );
2443 case PropertyType::Color:
2446 case PropertyType::Numeric:
2449 case PropertyType::Opacity:
2452 case PropertyType::Point:
2460 if ( color.type() != QVariant::String )
2462 context.
pushWarning( QObject::tr(
"%1: Could not parse non-string color %2, skipping" ).arg( context.
layerId(), color.toString() ) );
2471 hue = std::max( 0, color.hslHue() );
2472 saturation = color.hslSaturation() / 255.0 * 100;
2473 lightness = color.lightness() / 255.0 * 100;
2474 alpha = color.alpha();
2481 return QString::number( valueMin * multiplier );
2486 expression = QStringLiteral(
"scale_linear(@vector_tile_zoom,%1,%2,%3,%4)" ).arg( zoomMin )
2493 expression = QStringLiteral(
"scale_exp(@vector_tile_zoom,%1,%2,%3,%4,%5)" ).arg( zoomMin )
2500 if ( multiplier != 1 )
2501 return QStringLiteral(
"%1 * %2" ).arg( expression ).arg( multiplier );
2508 if ( style == QLatin1String(
"round" ) )
2509 return Qt::RoundCap;
2510 else if ( style == QLatin1String(
"square" ) )
2511 return Qt::SquareCap;
2518 if ( style == QLatin1String(
"bevel" ) )
2519 return Qt::BevelJoin;
2520 else if ( style == QLatin1String(
"round" ) )
2521 return Qt::RoundJoin;
2523 return Qt::MiterJoin;
2528 QString op = expression.value( 0 ).toString();
2529 if ( op == QLatin1String(
"all" )
2530 || op == QLatin1String(
"any" )
2531 || op == QLatin1String(
"none" ) )
2534 for (
int i = 1; i < expression.size(); ++i )
2536 QString part = parseValue( expression.at( i ), context );
2537 if ( part.isEmpty() )
2539 context.
pushWarning( QObject::tr(
"%1: Skipping unsupported expression" ).arg( context.
layerId() ) );
2545 if ( op == QLatin1String(
"none" ) )
2546 return QStringLiteral(
"NOT (%1)" ).arg( parts.join( QLatin1String(
") AND NOT (" ) ) );
2548 QString operatorString;
2549 if ( op == QLatin1String(
"all" ) )
2550 operatorString = QStringLiteral(
") AND (" );
2551 else if ( op == QLatin1String(
"any" ) )
2552 operatorString = QStringLiteral(
") OR (" );
2554 return QStringLiteral(
"(%1)" ).arg( parts.join( operatorString ) );
2556 else if ( op ==
'!' )
2559 QVariantList contraJsonExpr = expression.value( 1 ).toList();
2560 contraJsonExpr[0] = QString( op + contraJsonExpr[0].toString() );
2562 return parseKey( contraJsonExpr );
2564 else if ( op == QLatin1String(
"==" )
2565 || op == QLatin1String(
"!=" )
2566 || op == QLatin1String(
">=" )
2568 || op == QLatin1String(
"<=" )
2572 if ( op == QLatin1String(
"==" ) )
2573 op = QStringLiteral(
"IS" );
2574 else if ( op == QLatin1String(
"!=" ) )
2575 op = QStringLiteral(
"IS NOT" );
2576 return QStringLiteral(
"%1 %2 %3" ).arg( parseKey( expression.value( 1 ) ),
2577 op, parseValue( expression.value( 2 ), context ) );
2579 else if ( op == QLatin1String(
"has" ) )
2581 return parseKey( expression.value( 1 ) ) + QStringLiteral(
" IS NOT NULL" );
2583 else if ( op == QLatin1String(
"!has" ) )
2585 return parseKey( expression.value( 1 ) ) + QStringLiteral(
" IS NULL" );
2587 else if ( op == QLatin1String(
"in" ) || op == QLatin1String(
"!in" ) )
2589 const QString key = parseKey( expression.value( 1 ) );
2591 for (
int i = 2; i < expression.size(); ++i )
2593 QString part = parseValue( expression.at( i ), context );
2594 if ( part.isEmpty() )
2596 context.
pushWarning( QObject::tr(
"%1: Skipping unsupported expression" ).arg( context.
layerId() ) );
2601 if ( op == QLatin1String(
"in" ) )
2602 return QStringLiteral(
"%1 IN (%2)" ).arg( key, parts.join( QLatin1String(
", " ) ) );
2604 return QStringLiteral(
"(%1 IS NULL OR %1 NOT IN (%2))" ).arg( key, parts.join( QLatin1String(
", " ) ) );
2606 else if ( op == QLatin1String(
"get" ) )
2608 return parseKey( expression.value( 1 ) );
2610 else if ( op == QLatin1String(
"match" ) )
2612 const QString attribute = expression.value( 1 ).toList().value( 1 ).toString();
2614 if ( expression.size() == 5
2615 && expression.at( 3 ).type() == QVariant::Bool && expression.at( 3 ).toBool() ==
true
2616 && expression.at( 4 ).type() == QVariant::Bool && expression.at( 4 ).toBool() ==
false )
2619 if ( expression.at( 2 ).type() == QVariant::List || expression.at( 2 ).type() == QVariant::StringList )
2622 for (
const QVariant &p : expression.at( 2 ).toList() )
2627 if ( parts.size() > 1 )
2632 else if ( expression.at( 2 ).type() == QVariant::String || expression.at( 2 ).type() == QVariant::Int
2633 || expression.at( 2 ).type() == QVariant::Double )
2639 context.
pushWarning( QObject::tr(
"%1: Skipping unsupported expression" ).arg( context.
layerId() ) );
2645 QString caseString = QStringLiteral(
"CASE " );
2646 for (
int i = 2; i < expression.size() - 2; i += 2 )
2648 if ( expression.at( i ).type() == QVariant::List || expression.at( i ).type() == QVariant::StringList )
2651 for (
const QVariant &p : expression.at( i ).toList() )
2656 if ( parts.size() > 1 )
2661 else if ( expression.at( i ).type() == QVariant::String || expression.at( i ).type() == QVariant::Int
2662 || expression.at( i ).type() == QVariant::Double )
2673 else if ( op == QLatin1String(
"to-string" ) )
2675 return QStringLiteral(
"to_string(%1)" ).arg(
parseExpression( expression.value( 1 ).toList(), context ) );
2679 context.
pushWarning( QObject::tr(
"%1: Skipping unsupported expression" ).arg( context.
layerId() ) );
2688 context.
pushWarning( QObject::tr(
"%1: Could not retrieve sprite '%2'" ).arg( context.
layerId(), name ) );
2692 const QVariantMap spriteDefinition = context.
spriteDefinitions().value( name ).toMap();
2693 if ( spriteDefinition.size() == 0 )
2695 context.
pushWarning( QObject::tr(
"%1: Could not retrieve sprite '%2'" ).arg( context.
layerId(), name ) );
2699 const QImage sprite = context.
spriteImage().copy( spriteDefinition.value( QStringLiteral(
"x" ) ).toInt(),
2700 spriteDefinition.value( QStringLiteral(
"y" ) ).toInt(),
2701 spriteDefinition.value( QStringLiteral(
"width" ) ).toInt(),
2702 spriteDefinition.value( QStringLiteral(
"height" ) ).toInt() );
2703 if ( sprite.isNull() )
2705 context.
pushWarning( QObject::tr(
"%1: Could not retrieve sprite '%2'" ).arg( context.
layerId(), name ) );
2709 spriteSize = sprite.size() / spriteDefinition.value( QStringLiteral(
"pixelRatio" ) ).toDouble() * context.
pixelSizeConversionFactor();
2717 auto prepareBase64 = [](
const QImage & sprite )
2720 if ( !sprite.isNull() )
2723 QBuffer buffer( &blob );
2724 buffer.open( QIODevice::WriteOnly );
2725 sprite.save( &buffer,
"PNG" );
2727 QByteArray encoded = blob.toBase64();
2728 path = QString( encoded );
2729 path.prepend( QLatin1String(
"base64:" ) );
2734 switch ( value.type() )
2736 case QVariant::String:
2738 QString spriteName = value.toString();
2739 QRegularExpression fieldNameMatch( QStringLiteral(
"{([^}]+)}" ) );
2740 QRegularExpressionMatch match = fieldNameMatch.match( spriteName );
2741 if ( match.hasMatch() )
2743 const QString fieldName = match.captured( 1 );
2744 spriteProperty = QStringLiteral(
"CASE" );
2745 spriteSizeProperty = QStringLiteral(
"CASE" );
2747 spriteName.replace(
"(", QLatin1String(
"\\(" ) );
2748 spriteName.replace(
")", QLatin1String(
"\\)" ) );
2749 spriteName.replace( fieldNameMatch, QStringLiteral(
"([^\\/\\\\]+)" ) );
2750 QRegularExpression fieldValueMatch( spriteName );
2752 for (
const QString &name : spriteNames )
2754 match = fieldValueMatch.match( name );
2755 if ( match.hasMatch() )
2759 const QString fieldValue = match.captured( 1 );
2761 path = prepareBase64( sprite );
2762 if ( spritePath.isEmpty() && !path.isEmpty() )
2768 spriteProperty += QStringLiteral(
" WHEN \"%1\" = '%2' THEN '%3'" )
2769 .arg( fieldName, fieldValue, path );
2770 spriteSizeProperty += QStringLiteral(
" WHEN \"%1\" = '%2' THEN %3" )
2771 .arg( fieldName ).arg( fieldValue ).arg( size.width() );
2775 spriteProperty += QLatin1String(
" END" );
2776 spriteSizeProperty += QLatin1String(
" END" );
2780 spriteProperty.clear();
2781 spriteSizeProperty.clear();
2782 const QImage sprite =
retrieveSprite( spriteName, context, spriteSize );
2783 spritePath = prepareBase64( sprite );
2790 const QVariantList stops = value.toMap().value( QStringLiteral(
"stops" ) ).toList();
2791 if ( stops.size() == 0 )
2798 sprite =
retrieveSprite( stops.value( 0 ).toList().value( 1 ).toString(), context, spriteSize );
2799 spritePath = prepareBase64( sprite );
2801 spriteProperty = QStringLiteral(
"CASE WHEN @vector_tile_zoom < %1 THEN '%2'" )
2802 .arg( stops.value( 0 ).toList().value( 0 ).toString() )
2804 spriteSizeProperty = QStringLiteral(
"CASE WHEN @vector_tile_zoom < %1 THEN %2" )
2805 .arg( stops.value( 0 ).toList().value( 0 ).toString() )
2806 .arg( spriteSize.width() );
2808 for (
int i = 0; i < stops.size() - 1; ++i )
2811 sprite =
retrieveSprite( stops.value( 0 ).toList().value( 1 ).toString(), context, size );
2812 path = prepareBase64( sprite );
2814 spriteProperty += QStringLiteral(
" WHEN @vector_tile_zoom >= %1 AND @vector_tile_zoom < %2 "
2816 .arg( stops.value( i ).toList().value( 0 ).toString(),
2817 stops.value( i + 1 ).toList().value( 0 ).toString(),
2819 spriteSizeProperty += QStringLiteral(
" WHEN @vector_tile_zoom >= %1 AND @vector_tile_zoom < %2 "
2821 .arg( stops.value( i ).toList().value( 0 ).toString(),
2822 stops.value( i + 1 ).toList().value( 0 ).toString() )
2823 .arg( size.width() );
2825 sprite =
retrieveSprite( stops.last().toList().value( 1 ).toString(), context, size );
2826 path = prepareBase64( sprite );
2828 spriteProperty += QStringLiteral(
" WHEN @vector_tile_zoom >= %1 "
2830 .arg( stops.last().toList().value( 0 ).toString() )
2832 spriteSizeProperty += QStringLiteral(
" WHEN @vector_tile_zoom >= %1 "
2834 .arg( stops.last().toList().value( 0 ).toString() )
2835 .arg( size.width() );
2839 case QVariant::List:
2841 const QVariantList json = value.toList();
2842 const QString method = json.value( 0 ).toString();
2843 if ( method != QLatin1String(
"match" ) )
2845 context.
pushWarning( QObject::tr(
"%1: Could not interpret sprite value list with method %2" ).arg( context.
layerId(), method ) );
2849 const QString attribute =
parseExpression( json.value( 1 ).toList(), context );
2850 if ( attribute.isEmpty() )
2852 context.
pushWarning( QObject::tr(
"%1: Could not interpret match list" ).arg( context.
layerId() ) );
2856 spriteProperty = QStringLiteral(
"CASE " );
2857 spriteSizeProperty = QStringLiteral(
"CASE " );
2859 for (
int i = 2; i < json.length() - 1; i += 2 )
2861 const QVariantList keys = json.value( i ).toList();
2863 QStringList matchString;
2864 for (
const QVariant &key : keys )
2869 const QVariant value = json.value( i + 1 );
2871 const QImage sprite =
retrieveSprite( value.toString(), context, spriteSize );
2872 spritePath = prepareBase64( sprite );
2874 spriteProperty += QStringLiteral(
" WHEN %1 IN (%2) "
2875 "THEN '%3' " ).arg( attribute,
2876 matchString.join(
',' ),
2879 spriteSizeProperty += QStringLiteral(
" WHEN %1 IN (%2) "
2880 "THEN %3 " ).arg( attribute,
2881 matchString.join(
',' ) ).arg( spriteSize.width() );
2884 const QImage sprite =
retrieveSprite( json.constLast().toString(), context, spriteSize );
2885 spritePath = prepareBase64( sprite );
2887 spriteProperty += QStringLiteral(
"ELSE %1 END" ).arg( spritePath );
2888 spriteSizeProperty += QStringLiteral(
"ELSE %3 END" ).arg( spriteSize.width() );
2902 switch ( value.type() )
2904 case QVariant::List:
2905 case QVariant::StringList:
2908 case QVariant::String:
2912 case QVariant::Double:
2913 return value.toString();
2916 context.
pushWarning( QObject::tr(
"%1: Skipping unsupported expression part" ).arg( context.
layerId() ) );
2922 QString QgsMapBoxGlStyleConverter::parseKey(
const QVariant &value )
2924 if ( value.toString() == QLatin1String(
"$type" ) )
2925 return QStringLiteral(
"_geom_type" );
2926 else if ( value.type() == QVariant::List || value.type() == QVariant::StringList )
2928 if ( value.toList().size() > 1 )
2929 return value.toList().at( 1 ).toString();
2931 return value.toList().value( 0 ).toString();
2938 return mRenderer ? mRenderer->clone() :
nullptr;
2943 return mLabeling ? mLabeling->clone() :
nullptr;
2952 mWarnings << warning;
2967 return mSizeConversionFactor;
2972 mSizeConversionFactor = sizeConversionFactor;
2977 return mSpriteImage;
2982 return mSpriteDefinitions;
2987 mSpriteImage = image;
2988 mSpriteDefinitions = definitions;
A paint effect which blurs a source picture, using a number of different blur methods.
@ StackBlur
Stack blur, a fast but low quality blur. Valid blur level values are between 0 - 16.
void setBlurUnit(const QgsUnitTypes::RenderUnit unit)
Sets the units used for the blur level (radius).
void setBlurMethod(const BlurMethod method)
Sets the blur method (algorithm) to use for performing the blur.
void setBlurLevel(const double level)
Sets blur level (radius)
A paint effect which consists of a stack of other chained paint effects.
void appendEffect(QgsPaintEffect *effect)
Appends an effect to the end of the stack.
static QString quotedValue(const QVariant &value)
Returns a string representation of a literal value, including appropriate quotations where required.
static QString quotedString(QString text)
Returns a quoted version of a string (in single quotes)
static QString createFieldEqualityExpression(const QString &fieldName, const QVariant &value)
Create an expression allowing to evaluate if a field is equal to a value.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
static bool fontFamilyHasStyle(const QString &family, const QString &style)
Check whether font family on system has specific style.
static QVariant parseJson(const std::string &jsonString)
Converts JSON jsonString to a QVariant, in case of parsing error an invalid QVariant is returned.
void setPlacementFlags(QgsLabeling::LinePlacementFlags flags)
Returns the line placement flags, which dictate how line labels can be placed above or below the line...
void setFactor(double factor)
Sets the obstacle factor, where 1.0 = default, < 1.0 more likely to be covered by labels,...
@ AboveLine
Labels can be placed above a line feature. Unless MapOrientation is also specified this mode respects...
@ OnLine
Labels can be placed directly over a line feature.
@ BelowLine
Labels can be placed below a line feature. Unless MapOrientation is also specified this mode respects...
virtual void setWidth(double width)
Sets the width of the line symbol layer.
void setOffsetUnit(QgsUnitTypes::RenderUnit unit)
Sets the unit for the line's offset.
void setOffset(double offset)
Sets the line's offset.
Context for a MapBox GL style conversion operation.
void setLayerId(const QString &value)
Sets the layer ID of the layer currently being converted.
QStringList warnings() const
Returns a list of warning messages generated during the conversion.
void pushWarning(const QString &warning)
Pushes a warning message generated during the conversion.
double pixelSizeConversionFactor() const
Returns the pixel size conversion factor, used to scale the original pixel sizes when converting styl...
QgsUnitTypes::RenderUnit targetUnit() const
Returns the target unit type.
void setPixelSizeConversionFactor(double sizeConversionFactor)
Sets the pixel size conversion factor, used to scale the original pixel sizes when converting styles.
void setSprites(const QImage &image, const QVariantMap &definitions)
Sets the sprite image and definitions JSON to use during conversion.
QString layerId() const
Returns the layer ID of the layer currently being converted.
void setTargetUnit(QgsUnitTypes::RenderUnit targetUnit)
Sets the target unit type.
QImage spriteImage() const
Returns the sprite image to use during conversion, or an invalid image if this is not set.
void clearWarnings()
Clears the list of warning messages.
QVariantMap spriteDefinitions() const
Returns the sprite definitions to use during conversion.
static QString parseStops(double base, const QVariantList &stops, double multiplier, QgsMapBoxGlStyleConversionContext &context)
Parses a list of interpolation stops.
QgsVectorTileRenderer * renderer() const
Returns a new instance of a vector tile renderer representing the converted style,...
static bool parseFillLayer(const QVariantMap &jsonLayer, QgsVectorTileBasicRendererStyle &style, QgsMapBoxGlStyleConversionContext &context)
Parses a fill layer.
PropertyType
Property types, for interpolated value conversion.
@ Numeric
Numeric property (e.g. line width, text size)
@ Opacity
Opacity property.
@ Point
Point/offset property.
QgsVectorTileLabeling * labeling() const
Returns a new instance of a vector tile labeling representing the converted style,...
static QgsProperty parseInterpolateByZoom(const QVariantMap &json, QgsMapBoxGlStyleConversionContext &context, double multiplier=1, double *defaultNumber=nullptr)
Parses a numeric value which is interpolated by zoom range.
static Qt::PenJoinStyle parseJoinStyle(const QString &style)
Converts a value to Qt::PenJoinStyle enum from JSON value.
static QgsProperty parseInterpolateStringByZoom(const QVariantMap &json, QgsMapBoxGlStyleConversionContext &context, const QVariantMap &conversionMap, QString *defaultString=nullptr)
Interpolates a string by zoom.
static QgsProperty parseInterpolatePointByZoom(const QVariantMap &json, QgsMapBoxGlStyleConversionContext &context, double multiplier=1, QPointF *defaultPoint=nullptr)
Interpolates a point/offset with either scale_linear() or scale_exp() (depending on base value).
static bool parseCircleLayer(const QVariantMap &jsonLayer, QgsVectorTileBasicRendererStyle &style, QgsMapBoxGlStyleConversionContext &context)
Parses a circle layer.
Result convert(const QVariantMap &style, QgsMapBoxGlStyleConversionContext *context=nullptr)
Converts a JSON style map, and returns the resultant status of the conversion.
static QgsProperty parseInterpolateListByZoom(const QVariantList &json, PropertyType type, QgsMapBoxGlStyleConversionContext &context, double multiplier=1, int maxOpacity=255, QColor *defaultColor=nullptr, double *defaultNumber=nullptr)
Interpolates a list which starts with the interpolate function.
~QgsMapBoxGlStyleConverter()
Result
Result of conversion.
@ Success
Conversion was successful.
@ NoLayerList
No layer list was found in JSON input.
QgsMapBoxGlStyleConverter()
Constructor for QgsMapBoxGlStyleConverter.
static QImage retrieveSprite(const QString &name, QgsMapBoxGlStyleConversionContext &context, QSize &spriteSize)
Retrieves the sprite image with the specified name, taken from the specified context.
void parseLayers(const QVariantList &layers, QgsMapBoxGlStyleConversionContext *context=nullptr)
Parse list of layers from JSON.
static QgsProperty parseInterpolateColorByZoom(const QVariantMap &json, QgsMapBoxGlStyleConversionContext &context, QColor *defaultColor=nullptr)
Parses a color value which is interpolated by zoom range.
static QString retrieveSpriteAsBase64(const QVariant &value, QgsMapBoxGlStyleConversionContext &context, QSize &spriteSize, QString &spriteProperty, QString &spriteSizeProperty)
Retrieves the sprite image with the specified name, taken from the specified context as a base64 enco...
static QString parseExpression(const QVariantList &expression, QgsMapBoxGlStyleConversionContext &context)
Converts a MapBox GL expression to a QGIS expression.
static QColor parseColor(const QVariant &color, QgsMapBoxGlStyleConversionContext &context)
Parses a color in one of these supported formats:
static bool parseSymbolLayerAsRenderer(const QVariantMap &jsonLayer, QgsVectorTileBasicRendererStyle &rendererStyle, QgsMapBoxGlStyleConversionContext &context)
Parses a symbol layer as a renderer.
static void parseSymbolLayer(const QVariantMap &jsonLayer, QgsVectorTileBasicRendererStyle &rendererStyle, bool &hasRenderer, QgsVectorTileBasicLabelingStyle &labelingStyle, bool &hasLabeling, QgsMapBoxGlStyleConversionContext &context)
Parses a symbol layer as renderer or labeling.
static QString interpolateExpression(double zoomMin, double zoomMax, double valueMin, double valueMax, double base, double multiplier=1)
Generates an interpolation for values between valueMin and valueMax, scaled between the ranges zoomMi...
static bool parseLineLayer(const QVariantMap &jsonLayer, QgsVectorTileBasicRendererStyle &style, QgsMapBoxGlStyleConversionContext &context)
Parses a line layer.
static void colorAsHslaComponents(const QColor &color, int &hue, int &saturation, int &lightness, int &alpha)
Takes a QColor object and returns HSLA components in required format for QGIS color_hsla() expression...
static Qt::PenCapStyle parseCapStyle(const QString &style)
Converts a value to Qt::PenCapStyle enum from JSON value.
static QString parseOpacityStops(double base, const QVariantList &stops, int maxOpacity)
Takes values from stops and uses either scale_linear() or scale_exp() functions to interpolate alpha ...
static QString parseStringStops(const QVariantList &stops, QgsMapBoxGlStyleConversionContext &context, const QVariantMap &conversionMap, QString *defaultString=nullptr)
Parses a list of interpolation stops containing string values.
static QgsProperty parseInterpolateOpacityByZoom(const QVariantMap &json, int maxOpacity)
Interpolates opacity with either scale_linear() or scale_exp() (depending on base value).
static QgsProperty parseMatchList(const QVariantList &json, PropertyType type, QgsMapBoxGlStyleConversionContext &context, double multiplier=1, int maxOpacity=255, QColor *defaultColor=nullptr, double *defaultNumber=nullptr)
Parses and converts a match function value list.
static QgsProperty parseValueList(const QVariantList &json, PropertyType type, QgsMapBoxGlStyleConversionContext &context, double multiplier=1, int maxOpacity=255, QColor *defaultColor=nullptr, double *defaultNumber=nullptr)
Parses and converts a value list (e.g.
static QString parsePointStops(double base, const QVariantList &stops, QgsMapBoxGlStyleConversionContext &context, double multiplier=1)
Takes values from stops and uses either scale_linear() or scale_exp() functions to interpolate point/...
Line symbol layer type which draws repeating marker symbols along a line feature.
bool setSubSymbol(QgsSymbol *symbol) override
Sets layer's subsymbol. takes ownership of the passed symbol.
void setOutputUnit(QgsUnitTypes::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
virtual void setSize(double size)
Sets the symbol size.
void setAngle(double angle)
Sets the rotation angle for the marker.
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the symbol's size.
void setOffset(QPointF offset)
Sets the marker's offset, which is the horizontal and vertical displacement which the rendered marker...
void setOffsetUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the symbol's offset.
A marker symbol type, for rendering Point and MultiPoint geometries.
void setEnabled(bool enabled)
Sets whether the effect is enabled.
Contains settings for how a map layer will be labeled.
double yOffset
Vertical offset of label.
void setFormat(const QgsTextFormat &format)
Sets the label text formatting settings, e.g., font settings, buffer settings, etc.
double xOffset
Horizontal offset of label.
QuadrantPosition quadOffset
Sets the quadrant in which to offset labels from feature.
QgsUnitTypes::RenderUnit offsetUnits
Units for offsets of label.
@ Curved
Arranges candidates following the curvature of a line feature. Applies to line layers only.
@ Horizontal
Arranges horizontal candidates scattered throughout a polygon feature. Applies to polygon layers only...
@ OverPoint
Arranges candidates over a point (or centroid of a polygon), or at a preset offset from the point....
int priority
Label priority.
QgsUnitTypes::RenderUnit distUnits
Units the distance from feature to the label.
MultiLineAlign multilineAlign
Horizontal alignment of multi-line labels.
@ FontStyle
Font style name.
@ FontLetterSpacing
Letter spacing.
@ LinePlacementOptions
Line placement flags.
const QgsLabelLineSettings & lineSettings() const
Returns the label line settings, which contain settings related to how the label engine places and fo...
const QgsLabelObstacleSettings & obstacleSettings() const
Returns the label obstacle settings.
void setDataDefinedProperties(const QgsPropertyCollection &collection)
Sets the label's property collection, used for data defined overrides.
bool isExpression
true if this label is made from a expression string, e.g., FieldName || 'mm'
double dist
Distance from feature to the label.
QString fieldName
Name of field (or an expression) to use for label text.
int autoWrapLength
If non-zero, indicates that label text should be automatically wrapped to (ideally) the specified num...
A grouped map of multiple QgsProperty objects, each referenced by a integer key value.
QgsProperty property(int key) const override
Returns a matching property from the collection, if one exists.
QVariant value(int key, const QgsExpressionContext &context, const QVariant &defaultValue=QVariant()) const override
Returns the calculated value of the property with the specified key from within the collection.
void setProperty(int key, const QgsProperty &property)
Adds a property to the collection and takes ownership of it.
bool isActive(int key) const override
Returns true if the collection contains an active property with the specified key.
A store for object properties.
QString expressionString() const
Returns the expression used for the property value.
QVariant value(const QgsExpressionContext &context, const QVariant &defaultValue=QVariant(), bool *ok=nullptr) const
Calculates the current value of the property, including any transforms which are set for the property...
static QgsProperty fromExpression(const QString &expression, bool isActive=true)
Returns a new ExpressionBasedProperty created from the specified expression.
A class for filling symbols with a repeated raster image.
void setWidthUnit(const QgsUnitTypes::RenderUnit unit)
Sets the units for the image's width.
@ Viewport
Tiling is based on complete map viewport.
void setWidth(const double width)
Sets the width for scaling the image used in the fill.
void setOpacity(double opacity)
Sets the opacity for the raster image used in the fill.
void setImageFilePath(const QString &imagePath)
Sets the path to the raster image used for the fill.
void setCoordinateMode(FillCoordinateMode mode)
Set the coordinate mode for fill.
Raster marker symbol layer class.
void setOpacity(double opacity)
Set the marker opacity.
void setPath(const QString &path)
Set the marker raster image path.
void setBrushStyle(Qt::BrushStyle style)
void setStrokeStyle(Qt::PenStyle strokeStyle)
void setFillColor(const QColor &color) override
Set fill color.
void setOffset(QPointF offset)
Sets an offset by which polygons will be translated during rendering.
void setStrokeColor(const QColor &strokeColor) override
Set stroke color.
void setOutputUnit(QgsUnitTypes::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
void setOffsetUnit(QgsUnitTypes::RenderUnit unit)
Sets the unit for the fill's offset.
A simple line symbol layer, which renders lines using a line in a variety of styles (e....
void setPenCapStyle(Qt::PenCapStyle style)
Sets the pen cap style used to render the line (e.g.
void setUseCustomDashPattern(bool b)
Sets whether the line uses a custom dash pattern.
void setCustomDashVector(const QVector< qreal > &vector)
Sets the custom dash vector, which is the pattern of alternating drawn/skipped lengths used while ren...
void setPenJoinStyle(Qt::PenJoinStyle style)
Sets the pen join style used to render the line (e.g.
void setOutputUnit(QgsUnitTypes::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
Simple marker symbol layer, consisting of a rendered shape with solid fill color and an stroke.
void setStrokeWidthUnit(QgsUnitTypes::RenderUnit u)
Sets the unit for the width of the marker's stroke.
void setFillColor(const QColor &color) override
Set fill color.
void setStrokeWidth(double w)
Sets the width of the marker's stroke.
void setStrokeColor(const QColor &color) override
Sets the marker's stroke color.
static QColor parseColor(const QString &colorStr, bool strictEval=false)
Attempts to parse a string as a color using a variety of common formats, including hex codes,...
@ PropertyFile
Filename, eg for svg files.
@ PropertyAngle
Symbol angle.
@ PropertyOpacity
Opacity.
@ PropertyOffset
Symbol offset.
@ PropertyStrokeWidth
Stroke width.
@ PropertyFillColor
Fill color.
@ PropertyName
Name, eg shape name for simple markers.
@ PropertyInterval
Line marker interval.
@ PropertyStrokeColor
Stroke color.
@ PropertyWidth
Symbol width.
virtual void setColor(const QColor &color)
The fill color.
void setDataDefinedProperties(const QgsPropertyCollection &collection)
Sets the symbol layer's property collection, used for data defined overrides.
@ CentralPoint
Place symbols at the mid point of the line.
void setPlacement(Placement placement)
Sets the placement of the symbols.
Container for settings relating to a text background object.
void setMarkerSymbol(QgsMarkerSymbol *symbol)
Sets the current marker symbol for the background shape.
void setSizeType(SizeType type)
Sets the method used to determine the size of the background shape (e.g., fixed size or buffer around...
@ ShapeMarkerSymbol
Marker symbol.
void setType(ShapeType type)
Sets the type of background shape to draw (e.g., square, ellipse, SVG).
void setEnabled(bool enabled)
Sets whether the text background will be drawn.
void setSize(QSizeF size)
Sets the size of the background shape.
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units used for the shape's size.
void setColor(const QColor &color)
Sets the color for the buffer.
void setEnabled(bool enabled)
Sets whether the text buffer will be drawn.
void setPaintEffect(QgsPaintEffect *effect)
Sets the current paint effect for the buffer.
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units used for the buffer size.
void setSize(double size)
Sets the size of the buffer.
Container for all settings relating to text rendering.
void setColor(const QColor &color)
Sets the color that text will be rendered in.
void setSize(double size)
Sets the size for rendered text.
void setFont(const QFont &font)
Sets the font used for rendering text.
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the size of rendered text.
void setBackground(const QgsTextBackgroundSettings &backgroundSettings)
Sets the text's background settings.q.
QFont font() const
Returns the font used for rendering text.
QgsTextBufferSettings & buffer()
Returns a reference to the text buffer settings.
RenderUnit
Rendering size units.
Configuration of a single style within QgsVectorTileBasicLabeling.
void setGeometryType(QgsWkbTypes::GeometryType geomType)
Sets type of the geometry that will be used (point / line / polygon)
void setLayerName(const QString &name)
Sets name of the sub-layer to render (empty layer means that all layers match)
void setMinZoomLevel(int minZoom)
Sets minimum zoom level index (negative number means no limit)
void setFilterExpression(const QString &expr)
Sets filter expression (empty filter means that all features match)
void setMaxZoomLevel(int maxZoom)
Sets maximum zoom level index (negative number means no limit)
void setStyleName(const QString &name)
Sets human readable name of this style.
void setLabelSettings(const QgsPalLayerSettings &settings)
Sets labeling configuration of this style.
void setEnabled(bool enabled)
Sets whether this style is enabled (used for rendering)
Basic labeling configuration for vector tile layers.
Definition of map rendering of a subset of vector tile data.
void setEnabled(bool enabled)
Sets whether this style is enabled (used for rendering)
void setMinZoomLevel(int minZoom)
Sets minimum zoom level index (negative number means no limit)
void setLayerName(const QString &name)
Sets name of the sub-layer to render (empty layer means that all layers match)
void setGeometryType(QgsWkbTypes::GeometryType geomType)
Sets type of the geometry that will be used (point / line / polygon)
void setFilterExpression(const QString &expr)
Sets filter expression (empty filter means that all features match)
void setSymbol(QgsSymbol *sym)
Sets symbol for rendering. Takes ownership of the symbol.
void setStyleName(const QString &name)
Sets human readable name of this style.
void setMaxZoomLevel(int maxZoom)
Sets maximum zoom level index (negative number means no limit)
The default vector tile renderer implementation.
Base class for labeling configuration classes for vector tile layers.
Abstract base class for all vector tile renderer implementations.
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QList< QgsSymbolLayer * > QgsSymbolLayerList