41 #include <QRegularExpression>
51 if ( style.contains( QStringLiteral(
"layers" ) ) )
53 parseLayers( style.value( QStringLiteral(
"layers" ) ).toList(), context );
57 mError = QObject::tr(
"Could not find layers list in JSON" );
72 std::unique_ptr< QgsMapBoxGlStyleConversionContext > tmpContext;
75 tmpContext = std::make_unique< QgsMapBoxGlStyleConversionContext >();
76 context = tmpContext.get();
79 QList<QgsVectorTileBasicRendererStyle> rendererStyles;
80 QList<QgsVectorTileBasicLabelingStyle> labelingStyles;
82 for (
const QVariant &layer : layers )
84 const QVariantMap jsonLayer = layer.toMap();
86 const QString layerType = jsonLayer.value( QStringLiteral(
"type" ) ).toString();
87 if ( layerType == QLatin1String(
"background" ) )
90 const QString styleId = jsonLayer.value( QStringLiteral(
"id" ) ).toString();
92 const QString layerName = jsonLayer.value( QStringLiteral(
"source-layer" ) ).toString();
94 const int minZoom = jsonLayer.value( QStringLiteral(
"minzoom" ), QStringLiteral(
"-1" ) ).toInt();
95 const int maxZoom = jsonLayer.value( QStringLiteral(
"maxzoom" ), QStringLiteral(
"-1" ) ).toInt();
97 const bool enabled = jsonLayer.value( QStringLiteral(
"visibility" ) ).toString() != QLatin1String(
"none" );
99 QString filterExpression;
100 if ( jsonLayer.contains( QStringLiteral(
"filter" ) ) )
102 filterExpression =
parseExpression( jsonLayer.value( QStringLiteral(
"filter" ) ).toList(), *context );
108 bool hasRendererStyle =
false;
109 bool hasLabelingStyle =
false;
110 if ( layerType == QLatin1String(
"fill" ) )
112 hasRendererStyle =
parseFillLayer( jsonLayer, rendererStyle, *context );
114 else if ( layerType == QLatin1String(
"line" ) )
116 hasRendererStyle =
parseLineLayer( jsonLayer, rendererStyle, *context );
118 else if ( layerType == QLatin1String(
"circle" ) )
122 else if ( layerType == QLatin1String(
"symbol" ) )
124 parseSymbolLayer( jsonLayer, rendererStyle, hasRendererStyle, labelingStyle, hasLabelingStyle, *context );
128 mWarnings << QObject::tr(
"%1: Skipping unknown layer type %2" ).arg( context->
layerId(), layerType );
133 if ( hasRendererStyle )
141 rendererStyles.append( rendererStyle );
144 if ( hasLabelingStyle )
152 labelingStyles.append( labelingStyle );
155 mWarnings.append( context->
warnings() );
159 mRenderer = std::make_unique< QgsVectorTileBasicRenderer >();
161 renderer->setStyles( rendererStyles );
163 mLabeling = std::make_unique< QgsVectorTileBasicLabeling >();
165 labeling->setStyles( labelingStyles );
170 if ( !jsonLayer.contains( QStringLiteral(
"paint" ) ) )
172 context.
pushWarning( QObject::tr(
"%1: Layer has no paint property, skipping" ).arg( jsonLayer.value( QStringLiteral(
"id" ) ).toString() ) );
176 const QVariantMap jsonPaint = jsonLayer.value( QStringLiteral(
"paint" ) ).toMap();
183 if ( jsonPaint.contains( QStringLiteral(
"fill-color" ) ) )
185 const QVariant jsonFillColor = jsonPaint.
value( QStringLiteral(
"fill-color" ) );
186 switch ( jsonFillColor.type() )
193 case QVariant::StringList:
197 case QVariant::String:
198 fillColor =
parseColor( jsonFillColor.toString(), context );
211 fillColor = QColor( 0, 0, 0 );
214 QColor fillOutlineColor;
215 if ( !jsonPaint.contains( QStringLiteral(
"fill-outline-color" ) ) )
218 if ( fillColor.isValid() )
219 fillOutlineColor = fillColor;
229 const QVariant jsonFillOutlineColor = jsonPaint.value( QStringLiteral(
"fill-outline-color" ) );
230 switch ( jsonFillOutlineColor.type() )
237 case QVariant::StringList:
241 case QVariant::String:
242 fillOutlineColor =
parseColor( jsonFillOutlineColor.toString(), context );
251 double fillOpacity = -1.0;
252 double rasterOpacity = -1.0;
253 if ( jsonPaint.contains( QStringLiteral(
"fill-opacity" ) ) )
255 const QVariant jsonFillOpacity = jsonPaint.value( QStringLiteral(
"fill-opacity" ) );
256 switch ( jsonFillOpacity.type() )
259 case QVariant::Double:
260 fillOpacity = jsonFillOpacity.toDouble();
261 rasterOpacity = fillOpacity;
267 context.
pushWarning( QObject::tr(
"%1: Could not set opacity of layer, opacity already defined in fill color" ).arg( context.
layerId() ) );
278 case QVariant::StringList:
281 context.
pushWarning( QObject::tr(
"%1: Could not set opacity of layer, opacity already defined in fill color" ).arg( context.
layerId() ) );
298 QPointF fillTranslate;
299 if ( jsonPaint.contains( QStringLiteral(
"fill-translate" ) ) )
301 const QVariant jsonFillTranslate = jsonPaint.value( QStringLiteral(
"fill-translate" ) );
302 switch ( jsonFillTranslate.type() )
310 case QVariant::StringList:
321 std::unique_ptr< QgsSymbol > symbol( std::make_unique< QgsFillSymbol >() );
323 Q_ASSERT( fillSymbol );
326 symbol->setOutputUnit( context.
targetUnit() );
329 if ( !fillTranslate.isNull() )
335 if ( jsonPaint.contains( QStringLiteral(
"fill-pattern" ) ) )
339 const QVariant fillPatternJson = jsonPaint.value( QStringLiteral(
"fill-pattern" ) );
342 fillColor = QColor();
343 fillOutlineColor = QColor();
350 QString spriteProperty, spriteSizeProperty;
351 const QString sprite =
retrieveSpriteAsBase64( fillPatternJson, context, spriteSize, spriteProperty, spriteSizeProperty );
352 if ( !sprite.isEmpty() )
357 rasterFill->
setWidth( spriteSize.width() );
361 if ( rasterOpacity >= 0 )
366 if ( !spriteProperty.isEmpty() )
373 symbol->appendSymbolLayer( rasterFill );
379 if ( fillOpacity != -1 )
381 symbol->setOpacity( fillOpacity );
384 if ( fillOutlineColor.isValid() )
393 if ( fillColor.isValid() )
409 if ( !jsonLayer.contains( QStringLiteral(
"paint" ) ) )
411 context.
pushWarning( QObject::tr(
"%1: Style has no paint property, skipping" ).arg( context.
layerId() ) );
415 const QVariantMap jsonPaint = jsonLayer.value( QStringLiteral(
"paint" ) ).toMap();
416 if ( jsonPaint.contains( QStringLiteral(
"line-pattern" ) ) )
418 context.
pushWarning( QObject::tr(
"%1: Skipping unsupported line-pattern property" ).arg( context.
layerId() ) );
426 if ( jsonPaint.contains( QStringLiteral(
"line-color" ) ) )
428 const QVariant jsonLineColor = jsonPaint.
value( QStringLiteral(
"line-color" ) );
429 switch ( jsonLineColor.type() )
437 case QVariant::StringList:
442 case QVariant::String:
443 lineColor =
parseColor( jsonLineColor.toString(), context );
454 lineColor = QColor( 0, 0, 0 );
458 double lineWidth = 1.0;
459 if ( jsonPaint.contains( QStringLiteral(
"line-width" ) ) )
461 const QVariant jsonLineWidth = jsonPaint.value( QStringLiteral(
"line-width" ) );
462 switch ( jsonLineWidth.type() )
465 case QVariant::Double:
475 case QVariant::StringList:
485 double lineOffset = 0.0;
486 if ( jsonPaint.contains( QStringLiteral(
"line-offset" ) ) )
488 const QVariant jsonLineOffset = jsonPaint.value( QStringLiteral(
"line-offset" ) );
489 switch ( jsonLineOffset.type() )
492 case QVariant::Double:
502 case QVariant::StringList:
512 double lineOpacity = -1.0;
513 if ( jsonPaint.contains( QStringLiteral(
"line-opacity" ) ) )
515 const QVariant jsonLineOpacity = jsonPaint.value( QStringLiteral(
"line-opacity" ) );
516 switch ( jsonLineOpacity.type() )
519 case QVariant::Double:
520 lineOpacity = jsonLineOpacity.toDouble();
526 context.
pushWarning( QObject::tr(
"%1: Could not set opacity of layer, opacity already defined in stroke color" ).arg( context.
layerId() ) );
535 case QVariant::StringList:
538 context.
pushWarning( QObject::tr(
"%1: Could not set opacity of layer, opacity already defined in stroke color" ).arg( context.
layerId() ) );
552 QVector< double > dashVector;
553 if ( jsonPaint.contains( QStringLiteral(
"line-dasharray" ) ) )
555 const QVariant jsonLineDashArray = jsonPaint.value( QStringLiteral(
"line-dasharray" ) );
556 switch ( jsonLineDashArray.type() )
561 const QVariantList dashSource = jsonLineDashArray.toMap().value( QStringLiteral(
"stops" ) ).toList().last().toList().value( 1 ).toList();
562 for (
const QVariant &v : dashSource )
570 case QVariant::StringList:
572 const QVariantList dashSource = jsonLineDashArray.toList();
573 for (
const QVariant &v : dashSource )
586 Qt::PenCapStyle penCapStyle = Qt::FlatCap;
587 Qt::PenJoinStyle penJoinStyle = Qt::MiterJoin;
588 if ( jsonLayer.contains( QStringLiteral(
"layout" ) ) )
590 const QVariantMap jsonLayout = jsonLayer.value( QStringLiteral(
"layout" ) ).toMap();
591 if ( jsonLayout.contains( QStringLiteral(
"line-cap" ) ) )
593 penCapStyle =
parseCapStyle( jsonLayout.value( QStringLiteral(
"line-cap" ) ).toString() );
595 if ( jsonLayout.contains( QStringLiteral(
"line-join" ) ) )
597 penJoinStyle =
parseJoinStyle( jsonLayout.value( QStringLiteral(
"line-join" ) ).toString() );
601 std::unique_ptr< QgsSymbol > symbol( std::make_unique< QgsLineSymbol >() );
603 Q_ASSERT( lineSymbol );
606 symbol->setOutputUnit( context.
targetUnit() );
614 if ( lineOpacity != -1 )
616 symbol->setOpacity( lineOpacity );
618 if ( lineColor.isValid() )
622 if ( lineWidth != -1 )
626 if ( !dashVector.empty() )
639 if ( !jsonLayer.contains( QStringLiteral(
"paint" ) ) )
641 context.
pushWarning( QObject::tr(
"%1: Style has no paint property, skipping" ).arg( context.
layerId() ) );
645 const QVariantMap jsonPaint = jsonLayer.value( QStringLiteral(
"paint" ) ).toMap();
649 QColor circleFillColor;
650 if ( jsonPaint.contains( QStringLiteral(
"circle-color" ) ) )
652 const QVariant jsonCircleColor = jsonPaint.
value( QStringLiteral(
"circle-color" ) );
653 switch ( jsonCircleColor.type() )
660 case QVariant::StringList:
664 case QVariant::String:
665 circleFillColor =
parseColor( jsonCircleColor.toString(), context );
676 circleFillColor = QColor( 0, 0, 0 );
680 double circleDiameter = 10.0;
681 if ( jsonPaint.contains( QStringLiteral(
"circle-radius" ) ) )
683 const QVariant jsonCircleRadius = jsonPaint.value( QStringLiteral(
"circle-radius" ) );
684 switch ( jsonCircleRadius.type() )
687 case QVariant::Double:
697 case QVariant::StringList:
707 double circleOpacity = -1.0;
708 if ( jsonPaint.contains( QStringLiteral(
"circle-opacity" ) ) )
710 const QVariant jsonCircleOpacity = jsonPaint.value( QStringLiteral(
"circle-opacity" ) );
711 switch ( jsonCircleOpacity.type() )
714 case QVariant::Double:
715 circleOpacity = jsonCircleOpacity.toDouble();
723 case QVariant::StringList:
732 if ( ( circleOpacity != -1 ) && circleFillColor.isValid() )
734 circleFillColor.setAlphaF( circleOpacity );
738 QColor circleStrokeColor;
739 if ( jsonPaint.contains( QStringLiteral(
"circle-stroke-color" ) ) )
741 const QVariant jsonCircleStrokeColor = jsonPaint.value( QStringLiteral(
"circle-stroke-color" ) );
742 switch ( jsonCircleStrokeColor.type() )
749 case QVariant::StringList:
753 case QVariant::String:
754 circleStrokeColor =
parseColor( jsonCircleStrokeColor.toString(), context );
764 double circleStrokeWidth = -1.0;
765 if ( jsonPaint.contains( QStringLiteral(
"circle-stroke-width" ) ) )
767 const QVariant circleStrokeWidthJson = jsonPaint.value( QStringLiteral(
"circle-stroke-width" ) );
768 switch ( circleStrokeWidthJson.type() )
771 case QVariant::Double:
776 circleStrokeWidth = -1.0;
781 case QVariant::StringList:
791 double circleStrokeOpacity = -1.0;
792 if ( jsonPaint.contains( QStringLiteral(
"circle-stroke-opacity" ) ) )
794 const QVariant jsonCircleStrokeOpacity = jsonPaint.value( QStringLiteral(
"circle-stroke-opacity" ) );
795 switch ( jsonCircleStrokeOpacity.type() )
798 case QVariant::Double:
799 circleStrokeOpacity = jsonCircleStrokeOpacity.toDouble();
807 case QVariant::StringList:
816 if ( ( circleStrokeOpacity != -1 ) && circleStrokeColor.isValid() )
818 circleStrokeColor.setAlphaF( circleStrokeOpacity );
822 QPointF circleTranslate;
823 if ( jsonPaint.contains( QStringLiteral(
"circle-translate" ) ) )
825 const QVariant jsonCircleTranslate = jsonPaint.value( QStringLiteral(
"circle-translate" ) );
826 switch ( jsonCircleTranslate.type() )
834 case QVariant::StringList:
845 std::unique_ptr< QgsSymbol > symbol( std::make_unique< QgsMarkerSymbol >() );
847 Q_ASSERT( markerSymbolLayer );
850 symbol->setOutputUnit( context.
targetUnit() );
851 symbol->setDataDefinedProperties( ddProperties );
853 if ( !circleTranslate.isNull() )
855 markerSymbolLayer->
setOffset( circleTranslate );
859 if ( circleFillColor.isValid() )
863 if ( circleDiameter != -1 )
865 markerSymbolLayer->
setSize( circleDiameter );
868 if ( circleStrokeColor.isValid() )
872 if ( circleStrokeWidth != -1 )
888 if ( !jsonLayer.contains( QStringLiteral(
"layout" ) ) )
890 context.
pushWarning( QObject::tr(
"%1: Style layer has no layout property, skipping" ).arg( context.
layerId() ) );
893 const QVariantMap jsonLayout = jsonLayer.value( QStringLiteral(
"layout" ) ).toMap();
894 if ( !jsonLayout.contains( QStringLiteral(
"text-field" ) ) )
900 if ( !jsonLayer.contains( QStringLiteral(
"paint" ) ) )
902 context.
pushWarning( QObject::tr(
"%1: Style layer has no paint property, skipping" ).arg( context.
layerId() ) );
905 const QVariantMap jsonPaint = jsonLayer.value( QStringLiteral(
"paint" ) ).toMap();
911 if ( jsonLayout.contains( QStringLiteral(
"text-size" ) ) )
913 const QVariant jsonTextSize = jsonLayout.
value( QStringLiteral(
"text-size" ) );
914 switch ( jsonTextSize.type() )
917 case QVariant::Double:
928 case QVariant::StringList:
938 if ( textSizeProperty )
945 constexpr
double EM_TO_CHARS = 2.0;
947 double textMaxWidth = -1;
948 if ( jsonLayout.contains( QStringLiteral(
"text-max-width" ) ) )
950 const QVariant jsonTextMaxWidth = jsonLayout.value( QStringLiteral(
"text-max-width" ) );
951 switch ( jsonTextMaxWidth.type() )
954 case QVariant::Double:
955 textMaxWidth = jsonTextMaxWidth.toDouble() * EM_TO_CHARS;
963 case QVariant::StringList:
975 textMaxWidth = 10 * EM_TO_CHARS;
978 double textLetterSpacing = -1;
979 if ( jsonLayout.contains( QStringLiteral(
"text-letter-spacing" ) ) )
981 const QVariant jsonTextLetterSpacing = jsonLayout.value( QStringLiteral(
"text-letter-spacing" ) );
982 switch ( jsonTextLetterSpacing.type() )
985 case QVariant::Double:
986 textLetterSpacing = jsonTextLetterSpacing.toDouble();
994 case QVariant::StringList:
1005 bool foundFont =
false;
1007 if ( jsonLayout.contains( QStringLiteral(
"text-font" ) ) )
1009 auto splitFontFamily = [](
const QString & fontName, QString & family, QString & style ) ->
bool
1011 const QStringList textFontParts = fontName.split(
' ' );
1012 for (
int i = 1; i < textFontParts.size(); ++i )
1014 const QString candidateFontName = textFontParts.mid( 0, i ).join(
' ' );
1015 const QString candidateFontStyle = textFontParts.mid( i ).join(
' ' );
1018 family = candidateFontName;
1019 style = candidateFontStyle;
1024 if ( QFontDatabase().hasFamily( fontName ) )
1034 const QVariant jsonTextFont = jsonLayout.value( QStringLiteral(
"text-font" ) );
1035 if ( jsonTextFont.type() != QVariant::List && jsonTextFont.type() != QVariant::StringList && jsonTextFont.type() != QVariant::String
1036 && jsonTextFont.type() != QVariant::Map )
1042 switch ( jsonTextFont.type() )
1044 case QVariant::List:
1045 case QVariant::StringList:
1046 fontName = jsonTextFont.toList().value( 0 ).toString();
1049 case QVariant::String:
1050 fontName = jsonTextFont.toString();
1055 QString familyCaseString = QStringLiteral(
"CASE " );
1056 QString styleCaseString = QStringLiteral(
"CASE " );
1059 const QVariantList stops = jsonTextFont.toMap().value( QStringLiteral(
"stops" ) ).toList();
1062 for (
int i = 0; i < stops.length() - 1; ++i )
1065 const QVariant bz = stops.value( i ).toList().value( 0 );
1066 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();
1067 if ( bz.type() == QVariant::List || bz.type() == QVariant::StringList )
1069 context.
pushWarning( QObject::tr(
"%1: Expressions in interpolation function are not supported, skipping." ).arg( context.
layerId() ) );
1075 const QVariant tz = stops.value( i + 1 ).toList().value( 0 );
1076 if ( tz.type() == QVariant::List || tz.type() == QVariant::StringList )
1078 context.
pushWarning( QObject::tr(
"%1: Expressions in interpolation function are not supported, skipping." ).arg( context.
layerId() ) );
1083 if ( splitFontFamily( bv, fontFamily, fontStyle ) )
1085 familyCaseString += QStringLiteral(
"WHEN @vector_tile_zoom > %1 AND @vector_tile_zoom <= %2 "
1086 "THEN %3 " ).arg( bz.toString(),
1089 styleCaseString += QStringLiteral(
"WHEN @vector_tile_zoom > %1 AND @vector_tile_zoom <= %2 "
1090 "THEN %3 " ).arg( bz.toString(),
1096 context.
pushWarning( QObject::tr(
"%1: Referenced font %2 is not available on system" ).arg( context.
layerId(), bv ) );
1102 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();
1103 if ( splitFontFamily( bv, fontFamily, fontStyle ) )
1110 context.
pushWarning( QObject::tr(
"%1: Referenced font %2 is not available on system" ).arg( context.
layerId(), bv ) );
1117 fontName = fontFamily;
1128 if ( splitFontFamily( fontName, fontFamily, fontStyle ) )
1130 textFont = QFont( fontFamily );
1131 if ( !fontStyle.isEmpty() )
1132 textFont.setStyleName( fontStyle );
1142 fontName = QStringLiteral(
"Open Sans" );
1143 textFont = QFont( fontName );
1144 textFont.setStyleName( QStringLiteral(
"Regular" ) );
1149 fontName = QStringLiteral(
"Arial Unicode MS" );
1150 textFont = QFont( fontName );
1151 textFont.setStyleName( QStringLiteral(
"Regular" ) );
1156 fontName = QStringLiteral(
"Open Sans, Arial Unicode MS" );
1159 if ( !foundFont && !fontName.isEmpty() )
1161 context.
pushWarning( QObject::tr(
"%1: Referenced font %2 is not available on system" ).arg( context.
layerId(), fontName ) );
1166 if ( jsonPaint.contains( QStringLiteral(
"text-color" ) ) )
1168 const QVariant jsonTextColor = jsonPaint.value( QStringLiteral(
"text-color" ) );
1169 switch ( jsonTextColor.type() )
1175 case QVariant::List:
1176 case QVariant::StringList:
1180 case QVariant::String:
1181 textColor =
parseColor( jsonTextColor.toString(), context );
1192 textColor = QColor( 0, 0, 0 );
1197 if ( jsonPaint.contains( QStringLiteral(
"text-halo-color" ) ) )
1199 const QVariant jsonBufferColor = jsonPaint.value( QStringLiteral(
"text-halo-color" ) );
1200 switch ( jsonBufferColor.type() )
1206 case QVariant::List:
1207 case QVariant::StringList:
1211 case QVariant::String:
1212 bufferColor =
parseColor( jsonBufferColor.toString(), context );
1221 double bufferSize = 0.0;
1225 constexpr
double BUFFER_SIZE_SCALE = 2.0;
1226 if ( jsonPaint.contains( QStringLiteral(
"text-halo-width" ) ) )
1228 const QVariant jsonHaloWidth = jsonPaint.value( QStringLiteral(
"text-halo-width" ) );
1229 switch ( jsonHaloWidth.type() )
1232 case QVariant::Double:
1241 case QVariant::List:
1242 case QVariant::StringList:
1253 double haloBlurSize = 0;
1254 if ( jsonPaint.contains( QStringLiteral(
"text-halo-blur" ) ) )
1256 const QVariant jsonTextHaloBlur = jsonPaint.value( QStringLiteral(
"text-halo-blur" ) );
1257 switch ( jsonTextHaloBlur.type() )
1260 case QVariant::Double:
1274 if ( textColor.isValid() )
1276 if ( textSize >= 0 )
1280 if ( textLetterSpacing > 0 )
1282 QFont f = format.
font();
1283 f.setLetterSpacing( QFont::AbsoluteSpacing, textLetterSpacing );
1287 if ( bufferSize > 0 )
1294 if ( haloBlurSize > 0 )
1310 if ( textMaxWidth > 0 )
1317 auto processLabelField = [](
const QString & string,
bool & isExpression )->QString
1321 const QRegularExpression singleFieldRx( QStringLiteral(
"^{([^}]+)}$" ) );
1322 QRegularExpressionMatch match = singleFieldRx.match(
string );
1323 if ( match.hasMatch() )
1325 isExpression =
false;
1326 return match.captured( 1 );
1329 const QRegularExpression multiFieldRx( QStringLiteral(
"(?={[^}]+})" ) );
1330 const QStringList parts =
string.split( multiFieldRx );
1331 if ( parts.size() > 1 )
1333 isExpression =
true;
1336 for (
const QString &part : parts )
1338 if ( part.isEmpty() )
1342 const QStringList split = part.split(
'}' );
1344 if ( !split.at( 1 ).isEmpty() )
1347 return QStringLiteral(
"concat(%1)" ).arg( res.join(
',' ) );
1351 isExpression =
false;
1356 if ( jsonLayout.contains( QStringLiteral(
"text-field" ) ) )
1358 const QVariant jsonTextField = jsonLayout.value( QStringLiteral(
"text-field" ) );
1359 switch ( jsonTextField.type() )
1361 case QVariant::String:
1363 labelSettings.
fieldName = processLabelField( jsonTextField.toString(), labelSettings.
isExpression );
1367 case QVariant::List:
1368 case QVariant::StringList:
1370 const QVariantList textFieldList = jsonTextField.toList();
1378 if ( textFieldList.size() > 2 && textFieldList.at( 0 ).toString() == QLatin1String(
"format" ) )
1381 for (
int i = 1; i < textFieldList.size(); ++i )
1383 bool isExpression =
false;
1384 const QString part = processLabelField( textFieldList.at( i ).toString(), isExpression );
1385 if ( !isExpression )
1392 labelSettings.
fieldName = QStringLiteral(
"concat(%1)" ).arg( parts.join(
',' ) );
1413 if ( jsonLayout.contains( QStringLiteral(
"text-transform" ) ) )
1415 const QString textTransform = jsonLayout.value( QStringLiteral(
"text-transform" ) ).toString();
1416 if ( textTransform == QLatin1String(
"uppercase" ) )
1420 else if ( textTransform == QLatin1String(
"lowercase" ) )
1429 if ( jsonLayout.contains( QStringLiteral(
"symbol-placement" ) ) )
1431 const QString symbolPlacement = jsonLayout.value( QStringLiteral(
"symbol-placement" ) ).toString();
1432 if ( symbolPlacement == QLatin1String(
"line" ) )
1438 if ( jsonLayout.contains( QStringLiteral(
"text-rotation-alignment" ) ) )
1440 const QString textRotationAlignment = jsonLayout.value( QStringLiteral(
"text-rotation-alignment" ) ).toString();
1441 if ( textRotationAlignment == QLatin1String(
"viewport" ) )
1451 if ( jsonLayout.contains( QStringLiteral(
"text-offset" ) ) )
1453 const QVariant jsonTextOffset = jsonLayout.
value( QStringLiteral(
"text-offset" ) );
1456 switch ( jsonTextOffset.type() )
1459 textOffsetProperty =
parseInterpolatePointByZoom( jsonTextOffset.toMap(), context, !textSizeProperty ? textSize : 1.0, &textOffset );
1460 if ( !textSizeProperty )
1471 case QVariant::List:
1472 case QVariant::StringList:
1473 textOffset = QPointF( jsonTextOffset.toList().value( 0 ).toDouble() * textSize,
1474 jsonTextOffset.toList().value( 1 ).toDouble() * textSize );
1482 if ( !textOffset.isNull() )
1485 labelSettings.
dist = std::abs( textOffset.y() ) - textSize;
1487 if ( textSizeProperty && !textOffsetProperty )
1494 if ( textOffset.isNull() )
1502 if ( jsonLayout.contains( QStringLiteral(
"text-justify" ) ) )
1504 const QVariant jsonTextJustify = jsonLayout.value( QStringLiteral(
"text-justify" ) );
1507 QString textAlign = QStringLiteral(
"center" );
1509 const QVariantMap conversionMap
1511 { QStringLiteral(
"left" ), QStringLiteral(
"left" ) },
1512 { QStringLiteral(
"center" ), QStringLiteral(
"center" ) },
1513 { QStringLiteral(
"right" ), QStringLiteral(
"right" ) },
1514 { QStringLiteral(
"auto" ), QStringLiteral(
"follow" ) }
1517 switch ( jsonTextJustify.type() )
1519 case QVariant::String:
1520 textAlign = jsonTextJustify.toString();
1523 case QVariant::List:
1536 if ( textAlign == QLatin1String(
"left" ) )
1538 else if ( textAlign == QLatin1String(
"right" ) )
1540 else if ( textAlign == QLatin1String(
"center" ) )
1542 else if ( textAlign == QLatin1String(
"follow" ) )
1552 if ( jsonLayout.contains( QStringLiteral(
"text-anchor" ) ) )
1554 const QVariant jsonTextAnchor = jsonLayout.value( QStringLiteral(
"text-anchor" ) );
1557 const QVariantMap conversionMap
1559 { QStringLiteral(
"center" ), 4 },
1560 { QStringLiteral(
"left" ), 5 },
1561 { QStringLiteral(
"right" ), 3 },
1562 { QStringLiteral(
"top" ), 7 },
1563 { QStringLiteral(
"bottom" ), 1 },
1564 { QStringLiteral(
"top-left" ), 8 },
1565 { QStringLiteral(
"top-right" ), 6 },
1566 { QStringLiteral(
"bottom-left" ), 2 },
1567 { QStringLiteral(
"bottom-right" ), 0 },
1570 switch ( jsonTextAnchor.type() )
1572 case QVariant::String:
1573 textAnchor = jsonTextAnchor.toString();
1576 case QVariant::List:
1589 if ( textAnchor == QLatin1String(
"center" ) )
1591 else if ( textAnchor == QLatin1String(
"left" ) )
1593 else if ( textAnchor == QLatin1String(
"right" ) )
1595 else if ( textAnchor == QLatin1String(
"top" ) )
1597 else if ( textAnchor == QLatin1String(
"bottom" ) )
1599 else if ( textAnchor == QLatin1String(
"top-left" ) )
1601 else if ( textAnchor == QLatin1String(
"top-right" ) )
1603 else if ( textAnchor == QLatin1String(
"bottom-left" ) )
1605 else if ( textAnchor == QLatin1String(
"bottom-right" ) )
1610 if ( jsonLayout.contains( QStringLiteral(
"text-offset" ) ) )
1612 const QVariant jsonTextOffset = jsonLayout.value( QStringLiteral(
"text-offset" ) );
1615 switch ( jsonTextOffset.type() )
1621 case QVariant::List:
1622 case QVariant::StringList:
1623 textOffset = QPointF( jsonTextOffset.toList().value( 0 ).toDouble() * textSize,
1624 jsonTextOffset.toList().value( 1 ).toDouble() * textSize );
1632 if ( !textOffset.isNull() )
1635 labelSettings.
xOffset = textOffset.x();
1636 labelSettings.
yOffset = textOffset.y();
1641 if ( jsonLayout.contains( QStringLiteral(
"icon-image" ) ) &&
1645 QString spriteProperty, spriteSizeProperty;
1646 const QString sprite =
retrieveSpriteAsBase64( jsonLayout.value( QStringLiteral(
"icon-image" ) ), context, spriteSize, spriteProperty, spriteSizeProperty );
1647 if ( !sprite.isEmpty() )
1650 markerLayer->
setPath( sprite );
1651 markerLayer->
setSize( spriteSize.width() );
1654 if ( !spriteProperty.isEmpty() )
1666 backgroundSettings.
setSize( spriteSize );
1674 if ( textSize >= 0 )
1697 if ( !jsonLayer.contains( QStringLiteral(
"layout" ) ) )
1699 context.
pushWarning( QObject::tr(
"%1: Style layer has no layout property, skipping" ).arg( context.
layerId() ) );
1702 const QVariantMap jsonLayout = jsonLayer.value( QStringLiteral(
"layout" ) ).toMap();
1704 if ( jsonLayout.value( QStringLiteral(
"symbol-placement" ) ).toString() == QLatin1String(
"line" ) && !jsonLayout.contains( QStringLiteral(
"text-field" ) ) )
1708 double spacing = -1.0;
1709 if ( jsonLayout.contains( QStringLiteral(
"symbol-spacing" ) ) )
1711 const QVariant jsonSpacing = jsonLayout.
value( QStringLiteral(
"symbol-spacing" ) );
1712 switch ( jsonSpacing.type() )
1715 case QVariant::Double:
1723 case QVariant::List:
1724 case QVariant::StringList:
1739 bool rotateMarkers =
true;
1740 if ( jsonLayout.contains( QStringLiteral(
"icon-rotation-alignment" ) ) )
1742 const QString alignment = jsonLayout.value( QStringLiteral(
"icon-rotation-alignment" ) ).toString();
1743 if ( alignment == QLatin1String(
"map" ) || alignment == QLatin1String(
"auto" ) )
1745 rotateMarkers =
true;
1747 else if ( alignment == QLatin1String(
"viewport" ) )
1749 rotateMarkers =
false;
1754 double rotation = 0.0;
1755 if ( jsonLayout.contains( QStringLiteral(
"icon-rotate" ) ) )
1757 const QVariant jsonIconRotate = jsonLayout.
value( QStringLiteral(
"icon-rotate" ) );
1758 switch ( jsonIconRotate.type() )
1761 case QVariant::Double:
1762 rotation = jsonIconRotate.toDouble();
1769 case QVariant::List:
1770 case QVariant::StringList:
1791 QString spriteProperty, spriteSizeProperty;
1792 const QString sprite =
retrieveSpriteAsBase64( jsonLayout.value( QStringLiteral(
"icon-image" ) ), context, spriteSize, spriteProperty, spriteSizeProperty );
1793 if ( !sprite.isNull() )
1795 markerLayer->
setPath( sprite );
1796 markerLayer->
setSize( spriteSize.width() );
1799 if ( !spriteProperty.isEmpty() )
1806 if ( jsonLayout.contains( QStringLiteral(
"icon-size" ) ) )
1808 const QVariant jsonIconSize = jsonLayout.value( QStringLiteral(
"icon-size" ) );
1811 switch ( jsonIconSize.type() )
1814 case QVariant::Double:
1816 size = jsonIconSize.toDouble();
1817 if ( !spriteSizeProperty.isEmpty() )
1820 QgsProperty::fromExpression( QStringLiteral(
"with_variable('marker_size',%1,%2*@marker_size)" ).arg( spriteSizeProperty ).arg( size ) ) );
1829 case QVariant::List:
1830 case QVariant::StringList:
1835 markerLayer->
setSize( size * spriteSize.width() );
1838 if ( !spriteSizeProperty.isEmpty() )
1855 std::unique_ptr< QgsSymbol > symbol = std::make_unique< QgsLineSymbol >(
QgsSymbolLayerList() << lineSymbol );
1858 symbol->setOutputUnit( context.
targetUnit() );
1862 rendererStyle.
setSymbol( symbol.release() );
1865 else if ( jsonLayout.contains( QStringLiteral(
"icon-image" ) ) )
1867 const QVariantMap jsonPaint = jsonLayer.value( QStringLiteral(
"paint" ) ).toMap();
1870 QString spriteProperty, spriteSizeProperty;
1871 const QString sprite =
retrieveSpriteAsBase64( jsonLayout.value( QStringLiteral(
"icon-image" ) ), context, spriteSize, spriteProperty, spriteSizeProperty );
1872 if ( !sprite.isEmpty() )
1875 rasterMarker->
setPath( sprite );
1876 rasterMarker->
setSize( spriteSize.width() );
1880 if ( !spriteProperty.isEmpty() )
1886 if ( jsonLayout.contains( QStringLiteral(
"icon-size" ) ) )
1888 const QVariant jsonIconSize = jsonLayout.value( QStringLiteral(
"icon-size" ) );
1891 switch ( jsonIconSize.type() )
1894 case QVariant::Double:
1896 size = jsonIconSize.toDouble();
1897 if ( !spriteSizeProperty.isEmpty() )
1900 QgsProperty::fromExpression( QStringLiteral(
"with_variable('marker_size',%1,%2*@marker_size)" ).arg( spriteSizeProperty ).arg( size ) ) );
1909 case QVariant::List:
1910 case QVariant::StringList:
1915 rasterMarker->
setSize( size * spriteSize.width() );
1918 if ( !spriteSizeProperty.isEmpty() )
1931 double rotation = 0.0;
1932 if ( jsonLayout.contains( QStringLiteral(
"icon-rotate" ) ) )
1934 const QVariant jsonIconRotate = jsonLayout.value( QStringLiteral(
"icon-rotate" ) );
1935 switch ( jsonIconRotate.type() )
1938 case QVariant::Double:
1939 rotation = jsonIconRotate.toDouble();
1946 case QVariant::List:
1947 case QVariant::StringList:
1957 double iconOpacity = -1.0;
1958 if ( jsonPaint.contains( QStringLiteral(
"icon-opacity" ) ) )
1960 const QVariant jsonIconOpacity = jsonPaint.value( QStringLiteral(
"icon-opacity" ) );
1961 switch ( jsonIconOpacity.type() )
1964 case QVariant::Double:
1965 iconOpacity = jsonIconOpacity.toDouble();
1972 case QVariant::List:
1973 case QVariant::StringList:
1984 rasterMarker->
setAngle( rotation );
1985 if ( iconOpacity >= 0 )
1989 rendererStyle.
setSymbol( markerSymbol );
2000 const double base = json.
value( QStringLiteral(
"base" ), QStringLiteral(
"1" ) ).toDouble();
2001 const QVariantList stops = json.value( QStringLiteral(
"stops" ) ).toList();
2002 if ( stops.empty() )
2005 QString caseString = QStringLiteral(
"CASE " );
2007 for (
int i = 0; i < stops.length() - 1; ++i )
2010 const QString bz = stops.at( i ).toList().value( 0 ).toString();
2012 const QString tz = stops.at( i + 1 ).toList().value( 0 ).toString();
2014 const QColor bottomColor =
parseColor( stops.at( i ).toList().value( 1 ), context );
2015 const QColor topColor =
parseColor( stops.at( i + 1 ).toList().value( 1 ), context );
2028 caseString += QStringLiteral(
"WHEN @vector_tile_zoom >= %1 AND @vector_tile_zoom < %2 THEN color_hsla("
2029 "%3, %4, %5, %6) " ).arg( bz, tz,
2037 const QString tz = stops.last().toList().value( 0 ).toString();
2038 const QColor topColor =
parseColor( stops.last().toList().value( 1 ), context );
2045 caseString += QStringLiteral(
"WHEN @vector_tile_zoom >= %1 THEN color_hsla(%2, %3, %4, %5) "
2046 "ELSE color_hsla(%2, %3, %4, %5) END" ).arg( tz )
2047 .arg( tcHue ).arg( tcSat ).arg( tcLight ).arg( tcAlpha );
2050 if ( !stops.empty() && defaultColor )
2051 *defaultColor =
parseColor( stops.value( 0 ).toList().value( 1 ).toString(), context );
2058 const double base = json.
value( QStringLiteral(
"base" ), QStringLiteral(
"1" ) ).toDouble();
2059 const QVariantList stops = json.value( QStringLiteral(
"stops" ) ).toList();
2060 if ( stops.empty() )
2063 QString scaleExpression;
2064 if ( stops.size() <= 2 )
2067 stops.last().toList().value( 0 ).toDouble(),
2068 stops.value( 0 ).toList().value( 1 ).toDouble(),
2069 stops.last().toList().value( 1 ).toDouble(), base, multiplier );
2073 scaleExpression =
parseStops( base, stops, multiplier, context );
2076 if ( !stops.empty() && defaultNumber )
2077 *defaultNumber = stops.value( 0 ).toList().value( 1 ).toDouble() * multiplier;
2084 const double base = json.
value( QStringLiteral(
"base" ), QStringLiteral(
"1" ) ).toDouble();
2085 const QVariantList stops = json.value( QStringLiteral(
"stops" ) ).toList();
2086 if ( stops.empty() )
2089 QString scaleExpression;
2090 if ( stops.length() <= 2 )
2092 scaleExpression = QStringLiteral(
"set_color_part(@symbol_color, 'alpha', %1)" )
2094 stops.last().toList().value( 0 ).toDouble(),
2095 stops.value( 0 ).toList().value( 1 ).toDouble() * maxOpacity,
2096 stops.last().toList().value( 1 ).toDouble() * maxOpacity, base ) );
2107 QString caseString = QStringLiteral(
"CASE WHEN @vector_tile_zoom < %1 THEN set_color_part(@symbol_color, 'alpha', %2)" )
2108 .arg( stops.value( 0 ).toList().value( 0 ).toString() )
2109 .arg( stops.value( 0 ).toList().value( 1 ).toDouble() * maxOpacity );
2111 for (
int i = 0; i < stops.size() - 1; ++i )
2113 caseString += QStringLiteral(
" WHEN @vector_tile_zoom >= %1 AND @vector_tile_zoom < %2 "
2114 "THEN set_color_part(@symbol_color, 'alpha', %3)" )
2115 .arg( stops.value( i ).toList().value( 0 ).toString(),
2116 stops.value( i + 1 ).toList().value( 0 ).toString(),
2118 stops.value( i + 1 ).toList().value( 0 ).toDouble(),
2119 stops.value( i ).toList().value( 1 ).toDouble() * maxOpacity,
2120 stops.value( i + 1 ).toList().value( 1 ).toDouble() * maxOpacity, base ) );
2123 caseString += QStringLiteral(
" WHEN @vector_tile_zoom >= %1 "
2124 "THEN set_color_part(@symbol_color, 'alpha', %2) END" )
2125 .arg( stops.last().toList().value( 0 ).toString() )
2126 .arg( stops.last().toList().value( 1 ).toDouble() * maxOpacity );
2132 const double base = json.
value( QStringLiteral(
"base" ), QStringLiteral(
"1" ) ).toDouble();
2133 const QVariantList stops = json.value( QStringLiteral(
"stops" ) ).toList();
2134 if ( stops.empty() )
2137 QString scaleExpression;
2138 if ( stops.size() <= 2 )
2140 scaleExpression = QStringLiteral(
"array(%1,%2)" ).arg(
interpolateExpression( stops.value( 0 ).toList().value( 0 ).toDouble(),
2141 stops.last().toList().value( 0 ).toDouble(),
2142 stops.value( 0 ).toList().value( 1 ).toList().value( 0 ).toDouble(),
2143 stops.last().toList().value( 1 ).toList().value( 0 ).toDouble(), base, multiplier ),
2145 stops.last().toList().value( 0 ).toDouble(),
2146 stops.value( 0 ).toList().value( 1 ).toList().value( 1 ).toDouble(),
2147 stops.last().toList().value( 1 ).toList().value( 1 ).toDouble(), base, multiplier )
2152 scaleExpression =
parsePointStops( base, stops, context, multiplier );
2155 if ( !stops.empty() && defaultPoint )
2156 *defaultPoint = QPointF( stops.value( 0 ).toList().value( 1 ).toList().value( 0 ).toDouble() * multiplier,
2157 stops.value( 0 ).toList().value( 1 ).toList().value( 1 ).toDouble() * multiplier );
2163 const QVariantMap &conversionMap, QString *defaultString )
2165 const QVariantList stops = json.
value( QStringLiteral(
"stops" ) ).toList();
2166 if ( stops.empty() )
2169 QString scaleExpression =
parseStringStops( stops, context, conversionMap, defaultString );
2176 QString caseString = QStringLiteral(
"CASE " );
2178 for (
int i = 0; i < stops.length() - 1; ++i )
2181 const QVariant bz = stops.value( i ).toList().value( 0 );
2182 const QVariant bv = stops.value( i ).toList().value( 1 );
2183 if ( bv.type() != QVariant::List && bv.type() != QVariant::StringList )
2190 const QVariant tz = stops.value( i + 1 ).toList().value( 0 );
2191 const QVariant tv = stops.value( i + 1 ).toList().value( 1 );
2192 if ( tv.type() != QVariant::List && tv.type() != QVariant::StringList )
2198 caseString += QStringLiteral(
"WHEN @vector_tile_zoom > %1 AND @vector_tile_zoom <= %2 "
2199 "THEN array(%3,%4)" ).arg( bz.toString(),
2201 interpolateExpression( bz.toDouble(), tz.toDouble(), bv.toList().value( 0 ).toDouble(), tv.toList().value( 0 ).toDouble(), base, multiplier ),
2202 interpolateExpression( bz.toDouble(), tz.toDouble(), bv.toList().value( 1 ).toDouble(), tv.toList().value( 1 ).toDouble(), base, multiplier ) );
2204 caseString += QLatin1String(
"END" );
2210 QString caseString = QStringLiteral(
"CASE " );
2212 for (
int i = 0; i < stops.length() - 1; ++i )
2215 const QVariant bz = stops.value( i ).toList().value( 0 );
2216 const QVariant bv = stops.value( i ).toList().value( 1 );
2217 if ( bz.type() == QVariant::List || bz.type() == QVariant::StringList )
2219 context.
pushWarning( QObject::tr(
"%1: Expressions in interpolation function are not supported, skipping." ).arg( context.
layerId() ) );
2224 const QVariant tz = stops.value( i + 1 ).toList().value( 0 );
2225 const QVariant tv = stops.value( i + 1 ).toList().value( 1 );
2226 if ( tz.type() == QVariant::List || tz.type() == QVariant::StringList )
2228 context.
pushWarning( QObject::tr(
"%1: Expressions in interpolation function are not supported, skipping." ).arg( context.
layerId() ) );
2232 caseString += QStringLiteral(
"WHEN @vector_tile_zoom > %1 AND @vector_tile_zoom <= %2 "
2233 "THEN %3 " ).arg( bz.toString(),
2235 interpolateExpression( bz.toDouble(), tz.toDouble(), bv.toDouble(), tv.toDouble(), base, multiplier ) );
2238 const QVariant z = stops.last().toList().value( 0 );
2239 const QVariant v = stops.last().toList().value( 1 );
2240 caseString += QStringLiteral(
"WHEN @vector_tile_zoom > %1 "
2241 "THEN %2 END" ).arg( z.toString() ).arg( v.toDouble() * multiplier );
2247 QString caseString = QStringLiteral(
"CASE " );
2249 for (
int i = 0; i < stops.length() - 1; ++i )
2252 const QVariant bz = stops.value( i ).toList().value( 0 );
2253 const QString bv = stops.value( i ).toList().value( 1 ).toString();
2254 if ( bz.type() == QVariant::List || bz.type() == QVariant::StringList )
2256 context.
pushWarning( QObject::tr(
"%1: Expressions in interpolation function are not supported, skipping." ).arg( context.
layerId() ) );
2261 const QVariant tz = stops.value( i + 1 ).toList().value( 0 );
2262 if ( tz.type() == QVariant::List || tz.type() == QVariant::StringList )
2264 context.
pushWarning( QObject::tr(
"%1: Expressions in interpolation function are not supported, skipping." ).arg( context.
layerId() ) );
2268 caseString += QStringLiteral(
"WHEN @vector_tile_zoom > %1 AND @vector_tile_zoom <= %2 "
2269 "THEN %3 " ).arg( bz.toString(),
2273 caseString += QStringLiteral(
"ELSE %1 END" ).arg(
QgsExpression::quotedValue( conversionMap.value( stops.constLast().toList().value( 1 ).toString(),
2274 stops.constLast().toList().value( 1 ) ) ) );
2275 if ( defaultString )
2276 *defaultString = stops.constLast().toList().value( 1 ).toString();
2282 const QString method = json.
value( 0 ).toString();
2283 if ( method == QLatin1String(
"interpolate" ) )
2287 else if ( method == QLatin1String(
"match" ) )
2289 return parseMatchList( json, type, context, multiplier, maxOpacity, defaultColor, defaultNumber );
2293 context.
pushWarning( QObject::tr(
"%1: Could not interpret value list with method %2" ).arg( context.
layerId(), method ) );
2300 const QString attribute =
parseExpression( json.value( 1 ).toList(), context );
2301 if ( attribute.isEmpty() )
2303 context.
pushWarning( QObject::tr(
"%1: Could not interpret match list" ).arg( context.
layerId() ) );
2307 QString caseString = QStringLiteral(
"CASE " );
2309 for (
int i = 2; i < json.length() - 1; i += 2 )
2311 const QVariantList keys = json.value( i ).toList();
2313 QStringList matchString;
2314 for (
const QVariant &key : keys )
2319 const QVariant value = json.value( i + 1 );
2321 QString valueString;
2326 const QColor color =
parseColor( value, context );
2333 const double v = value.toDouble() * multiplier;
2334 valueString = QString::number( v );
2340 const double v = value.toDouble() * maxOpacity;
2341 valueString = QString::number( v );
2347 valueString = QStringLiteral(
"array(%1,%2)" ).arg( value.toList().value( 0 ).toDouble() * multiplier,
2348 value.toList().value( 0 ).toDouble() * multiplier );
2354 caseString += QStringLiteral(
"WHEN %1 IN (%2) THEN %3 " ).arg( attribute,
2355 matchString.join(
',' ), valueString );
2364 const QColor color =
parseColor( json.constLast(), context );
2366 *defaultColor = color;
2374 const double v = json.constLast().toDouble() * multiplier;
2375 if ( defaultNumber )
2377 elseValue = QString::number( v );
2383 const double v = json.constLast().toDouble() * maxOpacity;
2384 if ( defaultNumber )
2386 elseValue = QString::number( v );
2392 elseValue = QStringLiteral(
"array(%1,%2)" ).arg( json.constLast().toList().value( 0 ).toDouble() * multiplier,
2393 json.constLast().toList().value( 0 ).toDouble() * multiplier );
2399 caseString += QStringLiteral(
"ELSE %1 END" ).arg( elseValue );
2405 if ( json.value( 0 ).toString() != QLatin1String(
"interpolate" ) )
2407 context.
pushWarning( QObject::tr(
"%1: Could not interpret value list" ).arg( context.
layerId() ) );
2412 const QString technique = json.value( 1 ).toList().value( 0 ).toString();
2413 if ( technique == QLatin1String(
"linear" ) )
2415 else if ( technique == QLatin1String(
"exponential" ) )
2416 base = json.value( 1 ).toList(). value( 1 ).toDouble();
2417 else if ( technique == QLatin1String(
"cubic-bezier" ) )
2419 context.
pushWarning( QObject::tr(
"%1: Cubic-bezier interpolation is not supported, linear used instead." ).arg( context.
layerId() ) );
2424 context.
pushWarning( QObject::tr(
"%1: Skipping not implemented interpolation method %2" ).arg( context.
layerId(), technique ) );
2428 if ( json.value( 2 ).toList().value( 0 ).toString() != QLatin1String(
"zoom" ) )
2430 context.
pushWarning( QObject::tr(
"%1: Skipping not implemented interpolation input %2" ).arg( context.
layerId(), json.value( 2 ).toString() ) );
2436 for (
int i = 3; i < json.length(); i += 2 )
2438 stops.push_back( QVariantList() << json.value( i ).toString() << json.value( i + 1 ).toString() );
2442 props.insert( QStringLiteral(
"stops" ), stops );
2443 props.insert( QStringLiteral(
"base" ), base );
2446 case PropertyType::Color:
2449 case PropertyType::Numeric:
2452 case PropertyType::Opacity:
2455 case PropertyType::Point:
2463 if ( color.type() != QVariant::String )
2465 context.
pushWarning( QObject::tr(
"%1: Could not parse non-string color %2, skipping" ).arg( context.
layerId(), color.toString() ) );
2474 hue = std::max( 0, color.hslHue() );
2475 saturation = color.hslSaturation() / 255.0 * 100;
2476 lightness = color.lightness() / 255.0 * 100;
2477 alpha = color.alpha();
2484 return QString::number( valueMin * multiplier );
2489 expression = QStringLiteral(
"scale_linear(@vector_tile_zoom,%1,%2,%3,%4)" ).arg( zoomMin )
2496 expression = QStringLiteral(
"scale_exp(@vector_tile_zoom,%1,%2,%3,%4,%5)" ).arg( zoomMin )
2503 if ( multiplier != 1 )
2504 return QStringLiteral(
"%1 * %2" ).arg( expression ).arg( multiplier );
2511 if ( style == QLatin1String(
"round" ) )
2512 return Qt::RoundCap;
2513 else if ( style == QLatin1String(
"square" ) )
2514 return Qt::SquareCap;
2521 if ( style == QLatin1String(
"bevel" ) )
2522 return Qt::BevelJoin;
2523 else if ( style == QLatin1String(
"round" ) )
2524 return Qt::RoundJoin;
2526 return Qt::MiterJoin;
2531 QString op = expression.value( 0 ).toString();
2532 if ( op == QLatin1String(
"all" )
2533 || op == QLatin1String(
"any" )
2534 || op == QLatin1String(
"none" ) )
2537 for (
int i = 1; i < expression.size(); ++i )
2539 QString part = parseValue( expression.at( i ), context );
2540 if ( part.isEmpty() )
2542 context.
pushWarning( QObject::tr(
"%1: Skipping unsupported expression" ).arg( context.
layerId() ) );
2548 if ( op == QLatin1String(
"none" ) )
2549 return QStringLiteral(
"NOT (%1)" ).arg( parts.join( QLatin1String(
") AND NOT (" ) ) );
2551 QString operatorString;
2552 if ( op == QLatin1String(
"all" ) )
2553 operatorString = QStringLiteral(
") AND (" );
2554 else if ( op == QLatin1String(
"any" ) )
2555 operatorString = QStringLiteral(
") OR (" );
2557 return QStringLiteral(
"(%1)" ).arg( parts.join( operatorString ) );
2559 else if ( op ==
'!' )
2562 QVariantList contraJsonExpr = expression.value( 1 ).toList();
2563 contraJsonExpr[0] = QString( op + contraJsonExpr[0].toString() );
2565 return parseKey( contraJsonExpr );
2567 else if ( op == QLatin1String(
"==" )
2568 || op == QLatin1String(
"!=" )
2569 || op == QLatin1String(
">=" )
2571 || op == QLatin1String(
"<=" )
2575 if ( op == QLatin1String(
"==" ) )
2576 op = QStringLiteral(
"IS" );
2577 else if ( op == QLatin1String(
"!=" ) )
2578 op = QStringLiteral(
"IS NOT" );
2579 return QStringLiteral(
"%1 %2 %3" ).arg( parseKey( expression.value( 1 ) ),
2580 op, parseValue( expression.value( 2 ), context ) );
2582 else if ( op == QLatin1String(
"has" ) )
2584 return parseKey( expression.value( 1 ) ) + QStringLiteral(
" IS NOT NULL" );
2586 else if ( op == QLatin1String(
"!has" ) )
2588 return parseKey( expression.value( 1 ) ) + QStringLiteral(
" IS NULL" );
2590 else if ( op == QLatin1String(
"in" ) || op == QLatin1String(
"!in" ) )
2592 const QString key = parseKey( expression.value( 1 ) );
2594 for (
int i = 2; i < expression.size(); ++i )
2596 QString part = parseValue( expression.at( i ), context );
2597 if ( part.isEmpty() )
2599 context.
pushWarning( QObject::tr(
"%1: Skipping unsupported expression" ).arg( context.
layerId() ) );
2604 if ( op == QLatin1String(
"in" ) )
2605 return QStringLiteral(
"%1 IN (%2)" ).arg( key, parts.join( QLatin1String(
", " ) ) );
2607 return QStringLiteral(
"(%1 IS NULL OR %1 NOT IN (%2))" ).arg( key, parts.join( QLatin1String(
", " ) ) );
2609 else if ( op == QLatin1String(
"get" ) )
2611 return parseKey( expression.value( 1 ) );
2613 else if ( op == QLatin1String(
"match" ) )
2615 const QString attribute = expression.value( 1 ).toList().value( 1 ).toString();
2617 if ( expression.size() == 5
2618 && expression.at( 3 ).type() == QVariant::Bool && expression.at( 3 ).toBool() ==
true
2619 && expression.at( 4 ).type() == QVariant::Bool && expression.at( 4 ).toBool() ==
false )
2622 if ( expression.at( 2 ).type() == QVariant::List || expression.at( 2 ).type() == QVariant::StringList )
2625 for (
const QVariant &p : expression.at( 2 ).toList() )
2630 if ( parts.size() > 1 )
2635 else if ( expression.at( 2 ).type() == QVariant::String || expression.at( 2 ).type() == QVariant::Int
2636 || expression.at( 2 ).type() == QVariant::Double )
2642 context.
pushWarning( QObject::tr(
"%1: Skipping unsupported expression" ).arg( context.
layerId() ) );
2648 QString caseString = QStringLiteral(
"CASE " );
2649 for (
int i = 2; i < expression.size() - 2; i += 2 )
2651 if ( expression.at( i ).type() == QVariant::List || expression.at( i ).type() == QVariant::StringList )
2654 for (
const QVariant &p : expression.at( i ).toList() )
2659 if ( parts.size() > 1 )
2664 else if ( expression.at( i ).type() == QVariant::String || expression.at( i ).type() == QVariant::Int
2665 || expression.at( i ).type() == QVariant::Double )
2676 else if ( op == QLatin1String(
"to-string" ) )
2678 return QStringLiteral(
"to_string(%1)" ).arg(
parseExpression( expression.value( 1 ).toList(), context ) );
2682 context.
pushWarning( QObject::tr(
"%1: Skipping unsupported expression" ).arg( context.
layerId() ) );
2691 context.
pushWarning( QObject::tr(
"%1: Could not retrieve sprite '%2'" ).arg( context.
layerId(), name ) );
2695 const QVariantMap spriteDefinition = context.
spriteDefinitions().value( name ).toMap();
2696 if ( spriteDefinition.size() == 0 )
2698 context.
pushWarning( QObject::tr(
"%1: Could not retrieve sprite '%2'" ).arg( context.
layerId(), name ) );
2702 const QImage sprite = context.
spriteImage().copy( spriteDefinition.value( QStringLiteral(
"x" ) ).toInt(),
2703 spriteDefinition.value( QStringLiteral(
"y" ) ).toInt(),
2704 spriteDefinition.value( QStringLiteral(
"width" ) ).toInt(),
2705 spriteDefinition.value( QStringLiteral(
"height" ) ).toInt() );
2706 if ( sprite.isNull() )
2708 context.
pushWarning( QObject::tr(
"%1: Could not retrieve sprite '%2'" ).arg( context.
layerId(), name ) );
2712 spriteSize = sprite.size() / spriteDefinition.value( QStringLiteral(
"pixelRatio" ) ).toDouble() * context.
pixelSizeConversionFactor();
2720 auto prepareBase64 = [](
const QImage & sprite )
2723 if ( !sprite.isNull() )
2726 QBuffer buffer( &blob );
2727 buffer.open( QIODevice::WriteOnly );
2728 sprite.save( &buffer,
"PNG" );
2730 QByteArray encoded = blob.toBase64();
2731 path = QString( encoded );
2732 path.prepend( QLatin1String(
"base64:" ) );
2737 switch ( value.type() )
2739 case QVariant::String:
2741 QString spriteName = value.toString();
2742 QRegularExpression fieldNameMatch( QStringLiteral(
"{([^}]+)}" ) );
2743 QRegularExpressionMatch match = fieldNameMatch.match( spriteName );
2744 if ( match.hasMatch() )
2746 const QString fieldName = match.captured( 1 );
2747 spriteProperty = QStringLiteral(
"CASE" );
2748 spriteSizeProperty = QStringLiteral(
"CASE" );
2750 spriteName.replace(
"(", QLatin1String(
"\\(" ) );
2751 spriteName.replace(
")", QLatin1String(
"\\)" ) );
2752 spriteName.replace( fieldNameMatch, QStringLiteral(
"([^\\/\\\\]+)" ) );
2753 QRegularExpression fieldValueMatch( spriteName );
2755 for (
const QString &name : spriteNames )
2757 match = fieldValueMatch.match( name );
2758 if ( match.hasMatch() )
2762 const QString fieldValue = match.captured( 1 );
2764 path = prepareBase64( sprite );
2765 if ( spritePath.isEmpty() && !path.isEmpty() )
2771 spriteProperty += QStringLiteral(
" WHEN \"%1\" = '%2' THEN '%3'" )
2772 .arg( fieldName, fieldValue, path );
2773 spriteSizeProperty += QStringLiteral(
" WHEN \"%1\" = '%2' THEN %3" )
2774 .arg( fieldName ).arg( fieldValue ).arg( size.width() );
2778 spriteProperty += QLatin1String(
" END" );
2779 spriteSizeProperty += QLatin1String(
" END" );
2783 spriteProperty.clear();
2784 spriteSizeProperty.clear();
2785 const QImage sprite =
retrieveSprite( spriteName, context, spriteSize );
2786 spritePath = prepareBase64( sprite );
2793 const QVariantList stops = value.toMap().value( QStringLiteral(
"stops" ) ).toList();
2794 if ( stops.size() == 0 )
2801 sprite =
retrieveSprite( stops.value( 0 ).toList().value( 1 ).toString(), context, spriteSize );
2802 spritePath = prepareBase64( sprite );
2804 spriteProperty = QStringLiteral(
"CASE WHEN @vector_tile_zoom < %1 THEN '%2'" )
2805 .arg( stops.value( 0 ).toList().value( 0 ).toString() )
2807 spriteSizeProperty = QStringLiteral(
"CASE WHEN @vector_tile_zoom < %1 THEN %2" )
2808 .arg( stops.value( 0 ).toList().value( 0 ).toString() )
2809 .arg( spriteSize.width() );
2811 for (
int i = 0; i < stops.size() - 1; ++i )
2814 sprite =
retrieveSprite( stops.value( 0 ).toList().value( 1 ).toString(), context, size );
2815 path = prepareBase64( sprite );
2817 spriteProperty += QStringLiteral(
" WHEN @vector_tile_zoom >= %1 AND @vector_tile_zoom < %2 "
2819 .arg( stops.value( i ).toList().value( 0 ).toString(),
2820 stops.value( i + 1 ).toList().value( 0 ).toString(),
2822 spriteSizeProperty += QStringLiteral(
" WHEN @vector_tile_zoom >= %1 AND @vector_tile_zoom < %2 "
2824 .arg( stops.value( i ).toList().value( 0 ).toString(),
2825 stops.value( i + 1 ).toList().value( 0 ).toString() )
2826 .arg( size.width() );
2828 sprite =
retrieveSprite( stops.last().toList().value( 1 ).toString(), context, size );
2829 path = prepareBase64( sprite );
2831 spriteProperty += QStringLiteral(
" WHEN @vector_tile_zoom >= %1 "
2833 .arg( stops.last().toList().value( 0 ).toString() )
2835 spriteSizeProperty += QStringLiteral(
" WHEN @vector_tile_zoom >= %1 "
2837 .arg( stops.last().toList().value( 0 ).toString() )
2838 .arg( size.width() );
2842 case QVariant::List:
2844 const QVariantList json = value.toList();
2845 const QString method = json.value( 0 ).toString();
2846 if ( method != QLatin1String(
"match" ) )
2848 context.
pushWarning( QObject::tr(
"%1: Could not interpret sprite value list with method %2" ).arg( context.
layerId(), method ) );
2852 const QString attribute =
parseExpression( json.value( 1 ).toList(), context );
2853 if ( attribute.isEmpty() )
2855 context.
pushWarning( QObject::tr(
"%1: Could not interpret match list" ).arg( context.
layerId() ) );
2859 spriteProperty = QStringLiteral(
"CASE " );
2860 spriteSizeProperty = QStringLiteral(
"CASE " );
2862 for (
int i = 2; i < json.length() - 1; i += 2 )
2864 const QVariantList keys = json.value( i ).toList();
2866 QStringList matchString;
2867 for (
const QVariant &key : keys )
2872 const QVariant value = json.value( i + 1 );
2874 const QImage sprite =
retrieveSprite( value.toString(), context, spriteSize );
2875 spritePath = prepareBase64( sprite );
2877 spriteProperty += QStringLiteral(
" WHEN %1 IN (%2) "
2878 "THEN '%3' " ).arg( attribute,
2879 matchString.join(
',' ),
2882 spriteSizeProperty += QStringLiteral(
" WHEN %1 IN (%2) "
2883 "THEN %3 " ).arg( attribute,
2884 matchString.join(
',' ) ).arg( spriteSize.width() );
2887 const QImage sprite =
retrieveSprite( json.constLast().toString(), context, spriteSize );
2888 spritePath = prepareBase64( sprite );
2890 spriteProperty += QStringLiteral(
"ELSE %1 END" ).arg( spritePath );
2891 spriteSizeProperty += QStringLiteral(
"ELSE %3 END" ).arg( spriteSize.width() );
2905 switch ( value.type() )
2907 case QVariant::List:
2908 case QVariant::StringList:
2911 case QVariant::String:
2915 case QVariant::Double:
2916 return value.toString();
2919 context.
pushWarning( QObject::tr(
"%1: Skipping unsupported expression part" ).arg( context.
layerId() ) );
2925 QString QgsMapBoxGlStyleConverter::parseKey(
const QVariant &value )
2927 if ( value.toString() == QLatin1String(
"$type" ) )
2928 return QStringLiteral(
"_geom_type" );
2929 else if ( value.type() == QVariant::List || value.type() == QVariant::StringList )
2931 if ( value.toList().size() > 1 )
2932 return value.toList().at( 1 ).toString();
2934 return value.toList().value( 0 ).toString();
2941 return mRenderer ? mRenderer->clone() :
nullptr;
2946 return mLabeling ? mLabeling->clone() :
nullptr;
2955 mWarnings << warning;
2970 return mSizeConversionFactor;
2975 mSizeConversionFactor = sizeConversionFactor;
2980 return mSpriteImage;
2985 return mSpriteDefinitions;
2990 mSpriteImage = image;
2991 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 asExpression() const
Returns an expression string representing the state of the property, or an empty string if the proper...
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