43 #include <QRegularExpression>
53 if ( style.contains( QStringLiteral(
"layers" ) ) )
55 parseLayers( style.value( QStringLiteral(
"layers" ) ).toList(), context );
59 mError = QObject::tr(
"Could not find layers list in JSON" );
74 std::unique_ptr< QgsMapBoxGlStyleConversionContext > tmpContext;
77 tmpContext = std::make_unique< QgsMapBoxGlStyleConversionContext >();
78 context = tmpContext.get();
81 QList<QgsVectorTileBasicRendererStyle> rendererStyles;
82 QList<QgsVectorTileBasicLabelingStyle> labelingStyles;
85 bool hasRendererBackgroundStyle =
false;
87 for (
const QVariant &layer : layers )
89 const QVariantMap jsonLayer = layer.toMap();
91 const QString layerType = jsonLayer.value( QStringLiteral(
"type" ) ).toString();
92 if ( layerType == QLatin1String(
"background" ) )
94 hasRendererBackgroundStyle =
parseFillLayer( jsonLayer, rendererBackgroundStyle, *context,
true );
95 if ( hasRendererBackgroundStyle )
105 const QString styleId = jsonLayer.value( QStringLiteral(
"id" ) ).toString();
107 const QString layerName = jsonLayer.value( QStringLiteral(
"source-layer" ) ).toString();
109 const int minZoom = jsonLayer.value( QStringLiteral(
"minzoom" ), QStringLiteral(
"-1" ) ).toInt();
110 const int maxZoom = jsonLayer.value( QStringLiteral(
"maxzoom" ), QStringLiteral(
"-1" ) ).toInt();
112 const bool enabled = jsonLayer.value( QStringLiteral(
"visibility" ) ).toString() != QLatin1String(
"none" );
114 QString filterExpression;
115 if ( jsonLayer.contains( QStringLiteral(
"filter" ) ) )
117 filterExpression =
parseExpression( jsonLayer.value( QStringLiteral(
"filter" ) ).toList(), *context );
123 bool hasRendererStyle =
false;
124 bool hasLabelingStyle =
false;
125 if ( layerType == QLatin1String(
"fill" ) )
127 hasRendererStyle =
parseFillLayer( jsonLayer, rendererStyle, *context );
129 else if ( layerType == QLatin1String(
"line" ) )
131 hasRendererStyle =
parseLineLayer( jsonLayer, rendererStyle, *context );
133 else if ( layerType == QLatin1String(
"circle" ) )
137 else if ( layerType == QLatin1String(
"symbol" ) )
139 parseSymbolLayer( jsonLayer, rendererStyle, hasRendererStyle, labelingStyle, hasLabelingStyle, *context );
143 mWarnings << QObject::tr(
"%1: Skipping unknown layer type %2" ).arg( context->
layerId(), layerType );
148 if ( hasRendererStyle )
156 rendererStyles.append( rendererStyle );
159 if ( hasLabelingStyle )
167 labelingStyles.append( labelingStyle );
170 mWarnings.append( context->
warnings() );
174 if ( hasRendererBackgroundStyle )
175 rendererStyles.prepend( rendererBackgroundStyle );
177 mRenderer = std::make_unique< QgsVectorTileBasicRenderer >();
179 renderer->setStyles( rendererStyles );
181 mLabeling = std::make_unique< QgsVectorTileBasicLabeling >();
183 labeling->setStyles( labelingStyles );
188 const QVariantMap jsonPaint = jsonLayer.value( QStringLiteral(
"paint" ) ).toMap();
193 std::unique_ptr< QgsSymbol > symbol( std::make_unique< QgsFillSymbol >() );
197 if ( jsonPaint.contains( isBackgroundStyle ? QStringLiteral(
"background-color" ) : QStringLiteral(
"fill-color" ) ) )
199 const QVariant jsonFillColor = jsonPaint.value( isBackgroundStyle ? QStringLiteral(
"background-color" ) : QStringLiteral(
"fill-color" ) );
200 switch ( jsonFillColor.type() )
207 case QVariant::StringList:
211 case QVariant::String:
212 fillColor =
parseColor( jsonFillColor.toString(), context );
225 fillColor = QColor( 0, 0, 0 );
228 QColor fillOutlineColor;
229 if ( !isBackgroundStyle )
231 if ( !jsonPaint.contains( QStringLiteral(
"fill-outline-color" ) ) )
233 if ( fillColor.isValid() )
234 fillOutlineColor = fillColor;
242 const QVariant jsonFillOutlineColor = jsonPaint.value( QStringLiteral(
"fill-outline-color" ) );
243 switch ( jsonFillOutlineColor.type() )
250 case QVariant::StringList:
254 case QVariant::String:
255 fillOutlineColor =
parseColor( jsonFillOutlineColor.toString(), context );
265 double fillOpacity = -1.0;
266 double rasterOpacity = -1.0;
267 if ( jsonPaint.contains( isBackgroundStyle ? QStringLiteral(
"background-opacity" ) : QStringLiteral(
"fill-opacity" ) ) )
269 const QVariant jsonFillOpacity = jsonPaint.value( isBackgroundStyle ? QStringLiteral(
"background-opacity" ) : QStringLiteral(
"fill-opacity" ) );
270 switch ( jsonFillOpacity.type() )
273 case QVariant::Double:
274 fillOpacity = jsonFillOpacity.toDouble();
275 rasterOpacity = fillOpacity;
292 case QVariant::StringList:
312 QPointF fillTranslate;
313 if ( jsonPaint.contains( QStringLiteral(
"fill-translate" ) ) )
315 const QVariant jsonFillTranslate = jsonPaint.value( QStringLiteral(
"fill-translate" ) );
316 switch ( jsonFillTranslate.type() )
324 case QVariant::StringList:
336 Q_ASSERT( fillSymbol );
339 symbol->setOutputUnit( context.
targetUnit() );
342 if ( !fillTranslate.isNull() )
348 if ( jsonPaint.contains( isBackgroundStyle ? QStringLiteral(
"background-pattern" ) : QStringLiteral(
"fill-pattern" ) ) )
352 const QVariant fillPatternJson = jsonPaint.value( isBackgroundStyle ? QStringLiteral(
"background-pattern" ) : QStringLiteral(
"fill-pattern" ) );
355 fillColor = QColor();
356 fillOutlineColor = QColor();
363 QString spriteProperty, spriteSizeProperty;
364 const QString sprite =
retrieveSpriteAsBase64( fillPatternJson, context, spriteSize, spriteProperty, spriteSizeProperty );
365 if ( !sprite.isEmpty() )
370 rasterFill->
setWidth( spriteSize.width() );
374 if ( rasterOpacity >= 0 )
379 if ( !spriteProperty.isEmpty() )
386 symbol->appendSymbolLayer( rasterFill );
392 if ( fillOpacity != -1 )
394 symbol->setOpacity( fillOpacity );
397 if ( fillOutlineColor.isValid() )
406 if ( fillColor.isValid() )
422 if ( !jsonLayer.contains( QStringLiteral(
"paint" ) ) )
424 context.
pushWarning( QObject::tr(
"%1: Style has no paint property, skipping" ).arg( context.
layerId() ) );
429 QString rasterLineSprite;
431 const QVariantMap jsonPaint = jsonLayer.
value( QStringLiteral(
"paint" ) ).toMap();
432 if ( jsonPaint.contains( QStringLiteral(
"line-pattern" ) ) )
434 const QVariant jsonLinePattern = jsonPaint.value( QStringLiteral(
"line-pattern" ) );
435 switch ( jsonLinePattern.type() )
438 case QVariant::String:
441 QString spriteProperty, spriteSizeProperty;
442 rasterLineSprite =
retrieveSpriteAsBase64( jsonLinePattern, context, spriteSize, spriteProperty, spriteSizeProperty );
448 case QVariant::StringList:
453 if ( rasterLineSprite.isEmpty() )
456 context.
pushWarning( QObject::tr(
"%1: Skipping unsupported line-pattern property" ).arg( context.
layerId() ) );
463 if ( jsonPaint.contains( QStringLiteral(
"line-color" ) ) )
465 const QVariant jsonLineColor = jsonPaint.value( QStringLiteral(
"line-color" ) );
466 switch ( jsonLineColor.type() )
474 case QVariant::StringList:
479 case QVariant::String:
480 lineColor =
parseColor( jsonLineColor.toString(), context );
491 lineColor = QColor( 0, 0, 0 );
495 double lineWidth = 1.0;
497 if ( jsonPaint.contains( QStringLiteral(
"line-width" ) ) )
499 const QVariant jsonLineWidth = jsonPaint.
value( QStringLiteral(
"line-width" ) );
500 switch ( jsonLineWidth.type() )
503 case QVariant::Double:
514 case QVariant::StringList:
525 double lineOffset = 0.0;
526 if ( jsonPaint.contains( QStringLiteral(
"line-offset" ) ) )
528 const QVariant jsonLineOffset = jsonPaint.value( QStringLiteral(
"line-offset" ) );
529 switch ( jsonLineOffset.type() )
532 case QVariant::Double:
542 case QVariant::StringList:
552 double lineOpacity = -1.0;
553 if ( jsonPaint.contains( QStringLiteral(
"line-opacity" ) ) )
555 const QVariant jsonLineOpacity = jsonPaint.value( QStringLiteral(
"line-opacity" ) );
556 switch ( jsonLineOpacity.type() )
559 case QVariant::Double:
560 lineOpacity = jsonLineOpacity.toDouble();
566 context.
pushWarning( QObject::tr(
"%1: Could not set opacity of layer, opacity already defined in stroke color" ).arg( context.
layerId() ) );
575 case QVariant::StringList:
578 context.
pushWarning( QObject::tr(
"%1: Could not set opacity of layer, opacity already defined in stroke color" ).arg( context.
layerId() ) );
592 QVector< double > dashVector;
593 if ( jsonPaint.contains( QStringLiteral(
"line-dasharray" ) ) )
595 const QVariant jsonLineDashArray = jsonPaint.value( QStringLiteral(
"line-dasharray" ) );
596 switch ( jsonLineDashArray.type() )
600 QString arrayExpression;
603 arrayExpression = QStringLiteral(
"array_to_string(array_foreach(%1,@element * (%2)), ';')" )
604 .arg(
parseArrayStops( jsonLineDashArray.toMap().value( QStringLiteral(
"stops" ) ).toList(), context, 1 ),
609 arrayExpression = QStringLiteral(
"array_to_string(%1, ';')" ).arg(
parseArrayStops( jsonLineDashArray.toMap().value( QStringLiteral(
"stops" ) ).toList(), context, lineWidth ) );
613 const QVariantList dashSource = jsonLineDashArray.toMap().value( QStringLiteral(
"stops" ) ).toList().first().toList().value( 1 ).toList();
614 for (
const QVariant &v : dashSource )
616 dashVector << v.toDouble() * lineWidth;
622 case QVariant::StringList:
624 const QVariantList dashSource = jsonLineDashArray.toList();
626 QVector< double > rawDashVectorSizes;
627 rawDashVectorSizes.reserve( dashSource.size() );
628 for (
const QVariant &v : dashSource )
630 rawDashVectorSizes << v.toDouble();
634 if ( rawDashVectorSizes.size() == 1 )
637 rawDashVectorSizes.clear();
639 else if ( rawDashVectorSizes.size() % 2 == 1 )
643 rawDashVectorSizes[0] = rawDashVectorSizes[0] + rawDashVectorSizes[rawDashVectorSizes.size() - 1];
644 rawDashVectorSizes.resize( rawDashVectorSizes.size() - 1 );
647 if ( !rawDashVectorSizes.isEmpty() && ( !lineWidthProperty.
asExpression().isEmpty() ) )
649 QStringList dashArrayStringParts;
650 dashArrayStringParts.reserve( rawDashVectorSizes.size() );
651 for (
double v : std::as_const( rawDashVectorSizes ) )
656 QString arrayExpression = QStringLiteral(
"array_to_string(array_foreach(array(%1),@element * (%2)), ';')" )
657 .arg( dashArrayStringParts.join(
',' ),
663 for (
double v : std::as_const( rawDashVectorSizes ) )
665 dashVector << v *lineWidth;
677 Qt::PenCapStyle penCapStyle = Qt::FlatCap;
678 Qt::PenJoinStyle penJoinStyle = Qt::MiterJoin;
679 if ( jsonLayer.contains( QStringLiteral(
"layout" ) ) )
681 const QVariantMap jsonLayout = jsonLayer.value( QStringLiteral(
"layout" ) ).toMap();
682 if ( jsonLayout.contains( QStringLiteral(
"line-cap" ) ) )
684 penCapStyle =
parseCapStyle( jsonLayout.value( QStringLiteral(
"line-cap" ) ).toString() );
686 if ( jsonLayout.contains( QStringLiteral(
"line-join" ) ) )
688 penJoinStyle =
parseJoinStyle( jsonLayout.value( QStringLiteral(
"line-join" ) ).toString() );
692 std::unique_ptr< QgsSymbol > symbol( std::make_unique< QgsLineSymbol >() );
693 symbol->setOutputUnit( context.
targetUnit() );
695 if ( !rasterLineSprite.isEmpty() )
705 if ( lineOpacity != -1 )
707 symbol->setOpacity( lineOpacity );
709 if ( lineWidth != -1 )
713 symbol->changeSymbolLayer( 0, lineSymbol );
718 Q_ASSERT( lineSymbol );
728 if ( lineOpacity != -1 )
730 symbol->setOpacity( lineOpacity );
732 if ( lineColor.isValid() )
736 if ( lineWidth != -1 )
740 if ( !dashVector.empty() )
754 if ( !jsonLayer.contains( QStringLiteral(
"paint" ) ) )
756 context.
pushWarning( QObject::tr(
"%1: Style has no paint property, skipping" ).arg( context.
layerId() ) );
760 const QVariantMap jsonPaint = jsonLayer.value( QStringLiteral(
"paint" ) ).toMap();
764 QColor circleFillColor;
765 if ( jsonPaint.contains( QStringLiteral(
"circle-color" ) ) )
767 const QVariant jsonCircleColor = jsonPaint.
value( QStringLiteral(
"circle-color" ) );
768 switch ( jsonCircleColor.type() )
775 case QVariant::StringList:
779 case QVariant::String:
780 circleFillColor =
parseColor( jsonCircleColor.toString(), context );
791 circleFillColor = QColor( 0, 0, 0 );
795 double circleDiameter = 10.0;
796 if ( jsonPaint.contains( QStringLiteral(
"circle-radius" ) ) )
798 const QVariant jsonCircleRadius = jsonPaint.value( QStringLiteral(
"circle-radius" ) );
799 switch ( jsonCircleRadius.type() )
802 case QVariant::Double:
812 case QVariant::StringList:
822 double circleOpacity = -1.0;
823 if ( jsonPaint.contains( QStringLiteral(
"circle-opacity" ) ) )
825 const QVariant jsonCircleOpacity = jsonPaint.value( QStringLiteral(
"circle-opacity" ) );
826 switch ( jsonCircleOpacity.type() )
829 case QVariant::Double:
830 circleOpacity = jsonCircleOpacity.toDouble();
838 case QVariant::StringList:
847 if ( ( circleOpacity != -1 ) && circleFillColor.isValid() )
849 circleFillColor.setAlphaF( circleOpacity );
853 QColor circleStrokeColor;
854 if ( jsonPaint.contains( QStringLiteral(
"circle-stroke-color" ) ) )
856 const QVariant jsonCircleStrokeColor = jsonPaint.value( QStringLiteral(
"circle-stroke-color" ) );
857 switch ( jsonCircleStrokeColor.type() )
864 case QVariant::StringList:
868 case QVariant::String:
869 circleStrokeColor =
parseColor( jsonCircleStrokeColor.toString(), context );
879 double circleStrokeWidth = -1.0;
880 if ( jsonPaint.contains( QStringLiteral(
"circle-stroke-width" ) ) )
882 const QVariant circleStrokeWidthJson = jsonPaint.value( QStringLiteral(
"circle-stroke-width" ) );
883 switch ( circleStrokeWidthJson.type() )
886 case QVariant::Double:
891 circleStrokeWidth = -1.0;
896 case QVariant::StringList:
906 double circleStrokeOpacity = -1.0;
907 if ( jsonPaint.contains( QStringLiteral(
"circle-stroke-opacity" ) ) )
909 const QVariant jsonCircleStrokeOpacity = jsonPaint.value( QStringLiteral(
"circle-stroke-opacity" ) );
910 switch ( jsonCircleStrokeOpacity.type() )
913 case QVariant::Double:
914 circleStrokeOpacity = jsonCircleStrokeOpacity.toDouble();
922 case QVariant::StringList:
931 if ( ( circleStrokeOpacity != -1 ) && circleStrokeColor.isValid() )
933 circleStrokeColor.setAlphaF( circleStrokeOpacity );
937 QPointF circleTranslate;
938 if ( jsonPaint.contains( QStringLiteral(
"circle-translate" ) ) )
940 const QVariant jsonCircleTranslate = jsonPaint.value( QStringLiteral(
"circle-translate" ) );
941 switch ( jsonCircleTranslate.type() )
949 case QVariant::StringList:
960 std::unique_ptr< QgsSymbol > symbol( std::make_unique< QgsMarkerSymbol >() );
962 Q_ASSERT( markerSymbolLayer );
965 symbol->setOutputUnit( context.
targetUnit() );
966 symbol->setDataDefinedProperties( ddProperties );
968 if ( !circleTranslate.isNull() )
970 markerSymbolLayer->
setOffset( circleTranslate );
974 if ( circleFillColor.isValid() )
978 if ( circleDiameter != -1 )
980 markerSymbolLayer->
setSize( circleDiameter );
983 if ( circleStrokeColor.isValid() )
987 if ( circleStrokeWidth != -1 )
1000 hasLabeling =
false;
1001 hasRenderer =
false;
1003 if ( !jsonLayer.contains( QStringLiteral(
"layout" ) ) )
1005 context.
pushWarning( QObject::tr(
"%1: Style layer has no layout property, skipping" ).arg( context.
layerId() ) );
1008 const QVariantMap jsonLayout = jsonLayer.value( QStringLiteral(
"layout" ) ).toMap();
1009 if ( !jsonLayout.contains( QStringLiteral(
"text-field" ) ) )
1015 const QVariantMap jsonPaint = jsonLayer.value( QStringLiteral(
"paint" ) ).toMap();
1021 if ( jsonLayout.contains( QStringLiteral(
"text-size" ) ) )
1023 const QVariant jsonTextSize = jsonLayout.
value( QStringLiteral(
"text-size" ) );
1024 switch ( jsonTextSize.type() )
1027 case QVariant::Double:
1037 case QVariant::List:
1038 case QVariant::StringList:
1048 if ( textSizeProperty )
1055 constexpr
double EM_TO_CHARS = 2.0;
1057 double textMaxWidth = -1;
1058 if ( jsonLayout.contains( QStringLiteral(
"text-max-width" ) ) )
1060 const QVariant jsonTextMaxWidth = jsonLayout.value( QStringLiteral(
"text-max-width" ) );
1061 switch ( jsonTextMaxWidth.type() )
1064 case QVariant::Double:
1065 textMaxWidth = jsonTextMaxWidth.toDouble() * EM_TO_CHARS;
1072 case QVariant::List:
1073 case QVariant::StringList:
1085 textMaxWidth = 10 * EM_TO_CHARS;
1088 double textLetterSpacing = -1;
1089 if ( jsonLayout.contains( QStringLiteral(
"text-letter-spacing" ) ) )
1091 const QVariant jsonTextLetterSpacing = jsonLayout.value( QStringLiteral(
"text-letter-spacing" ) );
1092 switch ( jsonTextLetterSpacing.type() )
1095 case QVariant::Double:
1096 textLetterSpacing = jsonTextLetterSpacing.toDouble();
1103 case QVariant::List:
1104 case QVariant::StringList:
1115 bool foundFont =
false;
1117 QString fontStyleName;
1119 if ( jsonLayout.contains( QStringLiteral(
"text-font" ) ) )
1121 auto splitFontFamily = [](
const QString & fontName, QString & family, QString & style ) ->
bool
1123 QString matchedFamily;
1124 const QStringList textFontParts = fontName.split(
' ' );
1125 for (
int i = textFontParts.size() - 1; i >= 1; --i )
1127 const QString candidateFontFamily = textFontParts.mid( 0, i ).join(
' ' );
1128 const QString candidateFontStyle = textFontParts.mid( i ).join(
' ' );
1133 family = processedFontFamily;
1134 style = candidateFontStyle;
1139 if ( processedFontFamily == matchedFamily )
1141 family = processedFontFamily;
1142 style = candidateFontStyle;
1146 family = matchedFamily;
1147 style = processedFontFamily;
1148 style.replace( matchedFamily, QString() );
1149 style = style.trimmed();
1150 if ( !style.isEmpty() && !candidateFontStyle.isEmpty() )
1152 style += QStringLiteral(
" %1" ).arg( candidateFontStyle );
1160 if ( QFontDatabase().hasFamily( processedFontFamily ) )
1163 family = processedFontFamily;
1169 family = matchedFamily;
1176 const QVariant jsonTextFont = jsonLayout.value( QStringLiteral(
"text-font" ) );
1177 if ( jsonTextFont.type() != QVariant::List && jsonTextFont.type() != QVariant::StringList && jsonTextFont.type() != QVariant::String
1178 && jsonTextFont.type() != QVariant::Map )
1184 switch ( jsonTextFont.type() )
1186 case QVariant::List:
1187 case QVariant::StringList:
1188 fontName = jsonTextFont.toList().value( 0 ).toString();
1191 case QVariant::String:
1192 fontName = jsonTextFont.toString();
1197 QString familyCaseString = QStringLiteral(
"CASE " );
1198 QString styleCaseString = QStringLiteral(
"CASE " );
1200 const QVariantList stops = jsonTextFont.toMap().value( QStringLiteral(
"stops" ) ).toList();
1203 for (
int i = 0; i < stops.length() - 1; ++i )
1206 const QVariant bz = stops.value( i ).toList().value( 0 );
1207 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();
1208 if ( bz.type() == QVariant::List || bz.type() == QVariant::StringList )
1210 context.
pushWarning( QObject::tr(
"%1: Expressions in interpolation function are not supported, skipping." ).arg( context.
layerId() ) );
1216 const QVariant tz = stops.value( i + 1 ).toList().value( 0 );
1217 if ( tz.type() == QVariant::List || tz.type() == QVariant::StringList )
1219 context.
pushWarning( QObject::tr(
"%1: Expressions in interpolation function are not supported, skipping." ).arg( context.
layerId() ) );
1224 if ( splitFontFamily( bv, fontFamily, fontStyleName ) )
1226 familyCaseString += QStringLiteral(
"WHEN @vector_tile_zoom > %1 AND @vector_tile_zoom <= %2 "
1227 "THEN %3 " ).arg( bz.toString(),
1230 styleCaseString += QStringLiteral(
"WHEN @vector_tile_zoom > %1 AND @vector_tile_zoom <= %2 "
1231 "THEN %3 " ).arg( bz.toString(),
1237 context.
pushWarning( QObject::tr(
"%1: Referenced font %2 is not available on system" ).arg( context.
layerId(), bv ) );
1243 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();
1244 if ( splitFontFamily( bv, fontFamily, fontStyleName ) )
1251 context.
pushWarning( QObject::tr(
"%1: Referenced font %2 is not available on system" ).arg( context.
layerId(), bv ) );
1258 fontName = fontFamily;
1268 if ( splitFontFamily( fontName, fontFamily, fontStyleName ) )
1270 textFont = QFont( fontFamily );
1271 if ( !fontStyleName.isEmpty() )
1272 textFont.setStyleName( fontStyleName );
1282 fontName = QStringLiteral(
"Open Sans" );
1283 textFont = QFont( fontName );
1284 textFont.setStyleName( QStringLiteral(
"Regular" ) );
1285 fontStyleName = QStringLiteral(
"Regular" );
1290 fontName = QStringLiteral(
"Arial Unicode MS" );
1291 textFont = QFont( fontName );
1292 textFont.setStyleName( QStringLiteral(
"Regular" ) );
1293 fontStyleName = QStringLiteral(
"Regular" );
1298 fontName = QStringLiteral(
"Open Sans, Arial Unicode MS" );
1301 if ( !foundFont && !fontName.isEmpty() )
1303 context.
pushWarning( QObject::tr(
"%1: Referenced font %2 is not available on system" ).arg( context.
layerId(), fontName ) );
1308 if ( jsonPaint.contains( QStringLiteral(
"text-color" ) ) )
1310 const QVariant jsonTextColor = jsonPaint.value( QStringLiteral(
"text-color" ) );
1311 switch ( jsonTextColor.type() )
1317 case QVariant::List:
1318 case QVariant::StringList:
1322 case QVariant::String:
1323 textColor =
parseColor( jsonTextColor.toString(), context );
1334 textColor = QColor( 0, 0, 0 );
1339 if ( jsonPaint.contains( QStringLiteral(
"text-halo-color" ) ) )
1341 const QVariant jsonBufferColor = jsonPaint.value( QStringLiteral(
"text-halo-color" ) );
1342 switch ( jsonBufferColor.type() )
1348 case QVariant::List:
1349 case QVariant::StringList:
1353 case QVariant::String:
1354 bufferColor =
parseColor( jsonBufferColor.toString(), context );
1363 double bufferSize = 0.0;
1367 constexpr
double BUFFER_SIZE_SCALE = 2.0;
1368 if ( jsonPaint.contains( QStringLiteral(
"text-halo-width" ) ) )
1370 const QVariant jsonHaloWidth = jsonPaint.value( QStringLiteral(
"text-halo-width" ) );
1371 switch ( jsonHaloWidth.type() )
1374 case QVariant::Double:
1383 case QVariant::List:
1384 case QVariant::StringList:
1395 double haloBlurSize = 0;
1396 if ( jsonPaint.contains( QStringLiteral(
"text-halo-blur" ) ) )
1398 const QVariant jsonTextHaloBlur = jsonPaint.value( QStringLiteral(
"text-halo-blur" ) );
1399 switch ( jsonTextHaloBlur.type() )
1402 case QVariant::Double:
1416 if ( textColor.isValid() )
1418 if ( textSize >= 0 )
1423 if ( !fontStyleName.isEmpty() )
1426 if ( textLetterSpacing > 0 )
1428 QFont f = format.
font();
1429 f.setLetterSpacing( QFont::AbsoluteSpacing, textLetterSpacing );
1433 if ( bufferSize > 0 )
1440 if ( haloBlurSize > 0 )
1456 if ( textMaxWidth > 0 )
1462 if ( jsonLayout.contains( QStringLiteral(
"text-field" ) ) )
1464 const QVariant jsonTextField = jsonLayout.value( QStringLiteral(
"text-field" ) );
1465 switch ( jsonTextField.type() )
1467 case QVariant::String:
1469 labelSettings.
fieldName = processLabelField( jsonTextField.toString(), labelSettings.
isExpression );
1473 case QVariant::List:
1474 case QVariant::StringList:
1476 const QVariantList textFieldList = jsonTextField.toList();
1484 if ( textFieldList.size() > 2 && textFieldList.at( 0 ).toString() == QLatin1String(
"format" ) )
1487 for (
int i = 1; i < textFieldList.size(); ++i )
1489 bool isExpression =
false;
1490 const QString part = processLabelField( textFieldList.at( i ).toString(), isExpression );
1491 if ( !isExpression )
1498 labelSettings.
fieldName = QStringLiteral(
"concat(%1)" ).arg( parts.join(
',' ) );
1515 const QVariantList stops = jsonTextField.toMap().value( QStringLiteral(
"stops" ) ).toList();
1516 if ( !stops.empty() )
1523 context.
pushWarning( QObject::tr(
"%1: Skipping unsupported text-field dictionary" ).arg( context.
layerId() ) );
1534 if ( jsonLayout.contains( QStringLiteral(
"text-transform" ) ) )
1536 const QString textTransform = jsonLayout.value( QStringLiteral(
"text-transform" ) ).toString();
1537 if ( textTransform == QLatin1String(
"uppercase" ) )
1541 else if ( textTransform == QLatin1String(
"lowercase" ) )
1550 if ( jsonLayout.contains( QStringLiteral(
"symbol-placement" ) ) )
1552 const QString symbolPlacement = jsonLayout.value( QStringLiteral(
"symbol-placement" ) ).toString();
1553 if ( symbolPlacement == QLatin1String(
"line" ) )
1559 if ( jsonLayout.contains( QStringLiteral(
"text-rotation-alignment" ) ) )
1561 const QString textRotationAlignment = jsonLayout.value( QStringLiteral(
"text-rotation-alignment" ) ).toString();
1562 if ( textRotationAlignment == QLatin1String(
"viewport" ) )
1572 if ( jsonLayout.contains( QStringLiteral(
"text-offset" ) ) )
1574 const QVariant jsonTextOffset = jsonLayout.
value( QStringLiteral(
"text-offset" ) );
1577 switch ( jsonTextOffset.type() )
1580 textOffsetProperty =
parseInterpolatePointByZoom( jsonTextOffset.toMap(), context, !textSizeProperty ? textSize : 1.0, &textOffset );
1581 if ( !textSizeProperty )
1592 case QVariant::List:
1593 case QVariant::StringList:
1594 textOffset = QPointF( jsonTextOffset.toList().value( 0 ).toDouble() * textSize,
1595 jsonTextOffset.toList().value( 1 ).toDouble() * textSize );
1603 if ( !textOffset.isNull() )
1606 labelSettings.
dist = std::abs( textOffset.y() ) - textSize;
1608 if ( textSizeProperty && !textOffsetProperty )
1615 if ( textOffset.isNull() )
1623 if ( jsonLayout.contains( QStringLiteral(
"text-justify" ) ) )
1625 const QVariant jsonTextJustify = jsonLayout.value( QStringLiteral(
"text-justify" ) );
1628 QString textAlign = QStringLiteral(
"center" );
1630 const QVariantMap conversionMap
1632 { QStringLiteral(
"left" ), QStringLiteral(
"left" ) },
1633 { QStringLiteral(
"center" ), QStringLiteral(
"center" ) },
1634 { QStringLiteral(
"right" ), QStringLiteral(
"right" ) },
1635 { QStringLiteral(
"auto" ), QStringLiteral(
"follow" ) }
1638 switch ( jsonTextJustify.type() )
1640 case QVariant::String:
1641 textAlign = jsonTextJustify.toString();
1644 case QVariant::List:
1657 if ( textAlign == QLatin1String(
"left" ) )
1658 labelSettings.
multilineAlign = Qgis::LabelMultiLineAlignment::Left;
1659 else if ( textAlign == QLatin1String(
"right" ) )
1660 labelSettings.
multilineAlign = Qgis::LabelMultiLineAlignment::Right;
1661 else if ( textAlign == QLatin1String(
"center" ) )
1662 labelSettings.
multilineAlign = Qgis::LabelMultiLineAlignment::Center;
1663 else if ( textAlign == QLatin1String(
"follow" ) )
1664 labelSettings.
multilineAlign = Qgis::LabelMultiLineAlignment::FollowPlacement;
1668 labelSettings.
multilineAlign = Qgis::LabelMultiLineAlignment::Center;
1673 if ( jsonLayout.contains( QStringLiteral(
"text-anchor" ) ) )
1675 const QVariant jsonTextAnchor = jsonLayout.value( QStringLiteral(
"text-anchor" ) );
1678 const QVariantMap conversionMap
1680 { QStringLiteral(
"center" ), 4 },
1681 { QStringLiteral(
"left" ), 5 },
1682 { QStringLiteral(
"right" ), 3 },
1683 { QStringLiteral(
"top" ), 7 },
1684 { QStringLiteral(
"bottom" ), 1 },
1685 { QStringLiteral(
"top-left" ), 8 },
1686 { QStringLiteral(
"top-right" ), 6 },
1687 { QStringLiteral(
"bottom-left" ), 2 },
1688 { QStringLiteral(
"bottom-right" ), 0 },
1691 switch ( jsonTextAnchor.type() )
1693 case QVariant::String:
1694 textAnchor = jsonTextAnchor.toString();
1697 case QVariant::List:
1710 if ( textAnchor == QLatin1String(
"center" ) )
1711 labelSettings.
quadOffset = Qgis::LabelQuadrantPosition::Over;
1712 else if ( textAnchor == QLatin1String(
"left" ) )
1713 labelSettings.
quadOffset = Qgis::LabelQuadrantPosition::Right;
1714 else if ( textAnchor == QLatin1String(
"right" ) )
1715 labelSettings.
quadOffset = Qgis::LabelQuadrantPosition::Left;
1716 else if ( textAnchor == QLatin1String(
"top" ) )
1717 labelSettings.
quadOffset = Qgis::LabelQuadrantPosition::Below;
1718 else if ( textAnchor == QLatin1String(
"bottom" ) )
1719 labelSettings.
quadOffset = Qgis::LabelQuadrantPosition::Above;
1720 else if ( textAnchor == QLatin1String(
"top-left" ) )
1721 labelSettings.
quadOffset = Qgis::LabelQuadrantPosition::BelowRight;
1722 else if ( textAnchor == QLatin1String(
"top-right" ) )
1723 labelSettings.
quadOffset = Qgis::LabelQuadrantPosition::BelowLeft;
1724 else if ( textAnchor == QLatin1String(
"bottom-left" ) )
1725 labelSettings.
quadOffset = Qgis::LabelQuadrantPosition::AboveRight;
1726 else if ( textAnchor == QLatin1String(
"bottom-right" ) )
1727 labelSettings.
quadOffset = Qgis::LabelQuadrantPosition::AboveLeft;
1731 if ( jsonLayout.contains( QStringLiteral(
"text-offset" ) ) )
1733 const QVariant jsonTextOffset = jsonLayout.value( QStringLiteral(
"text-offset" ) );
1736 switch ( jsonTextOffset.type() )
1742 case QVariant::List:
1743 case QVariant::StringList:
1744 textOffset = QPointF( jsonTextOffset.toList().value( 0 ).toDouble() * textSize,
1745 jsonTextOffset.toList().value( 1 ).toDouble() * textSize );
1753 if ( !textOffset.isNull() )
1756 labelSettings.
xOffset = textOffset.x();
1757 labelSettings.
yOffset = textOffset.y();
1762 if ( jsonLayout.contains( QStringLiteral(
"icon-image" ) ) &&
1766 QString spriteProperty, spriteSizeProperty;
1767 const QString sprite =
retrieveSpriteAsBase64( jsonLayout.value( QStringLiteral(
"icon-image" ) ), context, spriteSize, spriteProperty, spriteSizeProperty );
1768 if ( !sprite.isEmpty() )
1771 markerLayer->
setPath( sprite );
1772 markerLayer->
setSize( spriteSize.width() );
1775 if ( !spriteProperty.isEmpty() )
1787 backgroundSettings.
setSize( spriteSize );
1795 if ( textSize >= 0 )
1818 if ( !jsonLayer.contains( QStringLiteral(
"layout" ) ) )
1820 context.
pushWarning( QObject::tr(
"%1: Style layer has no layout property, skipping" ).arg( context.
layerId() ) );
1823 const QVariantMap jsonLayout = jsonLayer.value( QStringLiteral(
"layout" ) ).toMap();
1825 if ( jsonLayout.value( QStringLiteral(
"symbol-placement" ) ).toString() == QLatin1String(
"line" ) && !jsonLayout.contains( QStringLiteral(
"text-field" ) ) )
1829 double spacing = -1.0;
1830 if ( jsonLayout.contains( QStringLiteral(
"symbol-spacing" ) ) )
1832 const QVariant jsonSpacing = jsonLayout.
value( QStringLiteral(
"symbol-spacing" ) );
1833 switch ( jsonSpacing.type() )
1836 case QVariant::Double:
1844 case QVariant::List:
1845 case QVariant::StringList:
1860 bool rotateMarkers =
true;
1861 if ( jsonLayout.contains( QStringLiteral(
"icon-rotation-alignment" ) ) )
1863 const QString alignment = jsonLayout.value( QStringLiteral(
"icon-rotation-alignment" ) ).toString();
1864 if ( alignment == QLatin1String(
"map" ) || alignment == QLatin1String(
"auto" ) )
1866 rotateMarkers =
true;
1868 else if ( alignment == QLatin1String(
"viewport" ) )
1870 rotateMarkers =
false;
1875 double rotation = 0.0;
1876 if ( jsonLayout.contains( QStringLiteral(
"icon-rotate" ) ) )
1878 const QVariant jsonIconRotate = jsonLayout.
value( QStringLiteral(
"icon-rotate" ) );
1879 switch ( jsonIconRotate.type() )
1882 case QVariant::Double:
1883 rotation = jsonIconRotate.toDouble();
1890 case QVariant::List:
1891 case QVariant::StringList:
1912 QString spriteProperty, spriteSizeProperty;
1913 const QString sprite =
retrieveSpriteAsBase64( jsonLayout.value( QStringLiteral(
"icon-image" ) ), context, spriteSize, spriteProperty, spriteSizeProperty );
1914 if ( !sprite.isNull() )
1916 markerLayer->
setPath( sprite );
1917 markerLayer->
setSize( spriteSize.width() );
1920 if ( !spriteProperty.isEmpty() )
1927 if ( jsonLayout.contains( QStringLiteral(
"icon-size" ) ) )
1929 const QVariant jsonIconSize = jsonLayout.value( QStringLiteral(
"icon-size" ) );
1932 switch ( jsonIconSize.type() )
1935 case QVariant::Double:
1937 size = jsonIconSize.toDouble();
1938 if ( !spriteSizeProperty.isEmpty() )
1941 QgsProperty::fromExpression( QStringLiteral(
"with_variable('marker_size',%1,%2*@marker_size)" ).arg( spriteSizeProperty ).arg( size ) ) );
1950 case QVariant::List:
1951 case QVariant::StringList:
1956 markerLayer->
setSize( size * spriteSize.width() );
1959 if ( !spriteSizeProperty.isEmpty() )
1976 std::unique_ptr< QgsSymbol > symbol = std::make_unique< QgsLineSymbol >(
QgsSymbolLayerList() << lineSymbol );
1979 symbol->setOutputUnit( context.
targetUnit() );
1983 rendererStyle.
setSymbol( symbol.release() );
1986 else if ( jsonLayout.contains( QStringLiteral(
"icon-image" ) ) )
1988 const QVariantMap jsonPaint = jsonLayer.value( QStringLiteral(
"paint" ) ).toMap();
1991 QString spriteProperty, spriteSizeProperty;
1992 const QString sprite =
retrieveSpriteAsBase64( jsonLayout.value( QStringLiteral(
"icon-image" ) ), context, spriteSize, spriteProperty, spriteSizeProperty );
1993 if ( !sprite.isEmpty() )
1996 rasterMarker->
setPath( sprite );
1997 rasterMarker->
setSize( spriteSize.width() );
2001 if ( !spriteProperty.isEmpty() )
2007 if ( jsonLayout.contains( QStringLiteral(
"icon-size" ) ) )
2009 const QVariant jsonIconSize = jsonLayout.value( QStringLiteral(
"icon-size" ) );
2012 switch ( jsonIconSize.type() )
2015 case QVariant::Double:
2017 size = jsonIconSize.toDouble();
2018 if ( !spriteSizeProperty.isEmpty() )
2021 QgsProperty::fromExpression( QStringLiteral(
"with_variable('marker_size',%1,%2*@marker_size)" ).arg( spriteSizeProperty ).arg( size ) ) );
2030 case QVariant::List:
2031 case QVariant::StringList:
2036 rasterMarker->
setSize( size * spriteSize.width() );
2039 if ( !spriteSizeProperty.isEmpty() )
2052 double rotation = 0.0;
2053 if ( jsonLayout.contains( QStringLiteral(
"icon-rotate" ) ) )
2055 const QVariant jsonIconRotate = jsonLayout.value( QStringLiteral(
"icon-rotate" ) );
2056 switch ( jsonIconRotate.type() )
2059 case QVariant::Double:
2060 rotation = jsonIconRotate.toDouble();
2067 case QVariant::List:
2068 case QVariant::StringList:
2078 double iconOpacity = -1.0;
2079 if ( jsonPaint.contains( QStringLiteral(
"icon-opacity" ) ) )
2081 const QVariant jsonIconOpacity = jsonPaint.value( QStringLiteral(
"icon-opacity" ) );
2082 switch ( jsonIconOpacity.type() )
2085 case QVariant::Double:
2086 iconOpacity = jsonIconOpacity.toDouble();
2093 case QVariant::List:
2094 case QVariant::StringList:
2105 rasterMarker->
setAngle( rotation );
2106 if ( iconOpacity >= 0 )
2110 rendererStyle.
setSymbol( markerSymbol );
2121 const double base = json.
value( QStringLiteral(
"base" ), QStringLiteral(
"1" ) ).toDouble();
2122 const QVariantList stops = json.value( QStringLiteral(
"stops" ) ).toList();
2123 if ( stops.empty() )
2126 QString caseString = QStringLiteral(
"CASE " );
2127 const QString colorComponent(
"color_part(%1,'%2')" );
2129 for (
int i = 0; i < stops.length() - 1; ++i )
2132 const QString bz = stops.at( i ).toList().value( 0 ).toString();
2134 const QString tz = stops.at( i + 1 ).toList().value( 0 ).toString();
2136 const QVariant bcVariant = stops.at( i ).toList().value( 1 );
2137 const QVariant tcVariant = stops.at( i + 1 ).toList().value( 1 );
2139 const QColor bottomColor =
parseColor( bcVariant.toString(), context );
2140 const QColor topColor =
parseColor( tcVariant.toString(), context );
2142 if ( i == 0 && bottomColor.isValid() )
2149 caseString += QStringLiteral(
"WHEN @vector_tile_zoom < %1 THEN color_hsla(%2, %3, %4, %5) " )
2150 .arg( bz ).arg( bcHue ).arg( bcSat ).arg( bcLight ).arg( bcAlpha );
2153 if ( bottomColor.isValid() && topColor.isValid() )
2165 caseString += QStringLiteral(
"WHEN @vector_tile_zoom >= %1 AND @vector_tile_zoom < %2 THEN color_hsla("
2166 "%3, %4, %5, %6) " ).arg( bz, tz,
2177 caseString += QStringLiteral(
"WHEN @vector_tile_zoom >= %1 AND @vector_tile_zoom < %2 THEN color_hsla("
2178 "%3, %4, %5, %6) " ).arg( bz, tz,
2179 interpolateExpression( bz.toDouble(), tz.toDouble(), colorComponent.arg( bottomColorExpr ).arg(
"hsl_hue" ), colorComponent.arg( topColorExpr ).arg(
"hsl_hue" ), base, 1, &context ),
2180 interpolateExpression( bz.toDouble(), tz.toDouble(), colorComponent.arg( bottomColorExpr ).arg(
"hsl_saturation" ), colorComponent.arg( topColorExpr ).arg(
"hsl_saturation" ), base, 1, &context ),
2181 interpolateExpression( bz.toDouble(), tz.toDouble(), colorComponent.arg( bottomColorExpr ).arg(
"lightness" ), colorComponent.arg( topColorExpr ).arg(
"lightness" ), base, 1, &context ),
2182 interpolateExpression( bz.toDouble(), tz.toDouble(), colorComponent.arg( bottomColorExpr ).arg(
"alpha" ), colorComponent.arg( topColorExpr ).arg(
"alpha" ), base, 1, &context ) );
2187 const QString tz = stops.last().toList().value( 0 ).toString();
2188 const QVariant tcVariant = stops.last().toList().value( 1 );
2189 const QColor topColor =
parseColor( stops.last().toList().value( 1 ), context );
2190 if ( topColor.isValid() )
2197 caseString += QStringLiteral(
"WHEN @vector_tile_zoom >= %1 THEN color_hsla(%2, %3, %4, %5) "
2198 "ELSE color_hsla(%2, %3, %4, %5) END" ).arg( tz ).arg( tcHue ).arg( tcSat ).arg( tcLight ).arg( tcAlpha );
2204 caseString += QStringLiteral(
"WHEN @vector_tile_zoom >= %1 THEN color_hsla(%2, %3, %4, %5) "
2205 "ELSE color_hsla(%2, %3, %4, %5) END" ).arg( tz )
2206 .arg( colorComponent.arg( topColorExpr ).arg(
"hsl_hue" ) ).arg( colorComponent.arg( topColorExpr ).arg(
"hsl_saturation" ) ).arg( colorComponent.arg( topColorExpr ).arg(
"lightness" ) ).arg( colorComponent.arg( topColorExpr ).arg(
"alpha" ) );
2209 if ( !stops.empty() && defaultColor )
2210 *defaultColor =
parseColor( stops.value( 0 ).toList().value( 1 ).toString(), context );
2217 const double base = json.
value( QStringLiteral(
"base" ), QStringLiteral(
"1" ) ).toDouble();
2218 const QVariantList stops = json.value( QStringLiteral(
"stops" ) ).toList();
2219 if ( stops.empty() )
2222 QString scaleExpression;
2223 if ( stops.size() <= 2 )
2226 stops.last().toList().value( 0 ).toDouble(),
2227 stops.value( 0 ).toList().value( 1 ),
2228 stops.last().toList().value( 1 ), base, multiplier, &context );
2232 scaleExpression =
parseStops( base, stops, multiplier, context );
2235 if ( !stops.empty() && defaultNumber )
2236 *defaultNumber = stops.value( 0 ).toList().value( 1 ).toDouble() * multiplier;
2246 context = *contextPtr;
2248 const double base = json.value( QStringLiteral(
"base" ), QStringLiteral(
"1" ) ).toDouble();
2249 const QVariantList stops = json.value( QStringLiteral(
"stops" ) ).toList();
2250 if ( stops.empty() )
2253 QString scaleExpression;
2254 if ( stops.length() <= 2 )
2256 const QVariant bv = stops.value( 0 ).toList().value( 1 );
2257 const QVariant tv = stops.last().toList().value( 1 );
2258 double bottom = 0.0;
2260 const bool numeric = numericArgumentsOnly( bv, tv, bottom, top );
2261 scaleExpression = QStringLiteral(
"set_color_part(@symbol_color, 'alpha', %1)" )
2263 stops.last().toList().value( 0 ).toDouble(),
2264 numeric ? QString::number( bottom * maxOpacity ) : QString(
"(%1) * %2" ).arg( parseValue( bv, context ) ).arg( maxOpacity ),
2265 numeric ? QString::number( top * maxOpacity ) : QString(
"(%1) * %2" ).arg( parseValue( tv, context ) ).arg( maxOpacity ), base, 1, &context ) );
2276 QString caseString = QStringLiteral(
"CASE WHEN @vector_tile_zoom < %1 THEN set_color_part(@symbol_color, 'alpha', %2)" )
2277 .arg( stops.value( 0 ).toList().value( 0 ).toString() )
2278 .arg( stops.value( 0 ).toList().value( 1 ).toDouble() * maxOpacity );
2280 for (
int i = 0; i < stops.size() - 1; ++i )
2282 const QVariant bv = stops.value( i ).toList().value( 1 );
2283 const QVariant tv = stops.value( i + 1 ).toList().value( 1 );
2284 double bottom = 0.0;
2286 const bool numeric = numericArgumentsOnly( bv, tv, bottom, top );
2288 caseString += QStringLiteral(
" WHEN @vector_tile_zoom >= %1 AND @vector_tile_zoom < %2 "
2289 "THEN set_color_part(@symbol_color, 'alpha', %3)" )
2290 .arg( stops.value( i ).toList().value( 0 ).toString(),
2291 stops.value( i + 1 ).toList().value( 0 ).toString(),
2293 stops.value( i + 1 ).toList().value( 0 ).toDouble(),
2294 numeric ? QString::number( bottom * maxOpacity ) : QString(
"(%1) * %2" ).arg( parseValue( bv, context ) ).arg( maxOpacity ),
2295 numeric ? QString::number( top * maxOpacity ) : QString(
"(%1) * %2" ).arg( parseValue( tv, context ) ).arg( maxOpacity ),
2296 base, 1, &context ) );
2299 caseString += QStringLiteral(
" WHEN @vector_tile_zoom >= %1 "
2300 "THEN set_color_part(@symbol_color, 'alpha', %2) END" )
2301 .arg( stops.last().toList().value( 0 ).toString() )
2302 .arg( stops.last().toList().value( 1 ).toDouble() * maxOpacity );
2308 const double base = json.
value( QStringLiteral(
"base" ), QStringLiteral(
"1" ) ).toDouble();
2309 const QVariantList stops = json.value( QStringLiteral(
"stops" ) ).toList();
2310 if ( stops.empty() )
2313 QString scaleExpression;
2314 if ( stops.size() <= 2 )
2316 scaleExpression = QStringLiteral(
"array(%1,%2)" ).arg(
interpolateExpression( stops.value( 0 ).toList().value( 0 ).toDouble(),
2317 stops.last().toList().value( 0 ).toDouble(),
2318 stops.value( 0 ).toList().value( 1 ).toList().value( 0 ),
2319 stops.last().toList().value( 1 ).toList().value( 0 ), base, multiplier, &context ),
2321 stops.last().toList().value( 0 ).toDouble(),
2322 stops.value( 0 ).toList().value( 1 ).toList().value( 1 ),
2323 stops.last().toList().value( 1 ).toList().value( 1 ), base, multiplier, &context )
2328 scaleExpression =
parsePointStops( base, stops, context, multiplier );
2331 if ( !stops.empty() && defaultPoint )
2332 *defaultPoint = QPointF( stops.value( 0 ).toList().value( 1 ).toList().value( 0 ).toDouble() * multiplier,
2333 stops.value( 0 ).toList().value( 1 ).toList().value( 1 ).toDouble() * multiplier );
2339 const QVariantMap &conversionMap, QString *defaultString )
2341 const QVariantList stops = json.
value( QStringLiteral(
"stops" ) ).toList();
2342 if ( stops.empty() )
2345 const QString scaleExpression =
parseStringStops( stops, context, conversionMap, defaultString );
2352 QString caseString = QStringLiteral(
"CASE " );
2354 for (
int i = 0; i < stops.length() - 1; ++i )
2357 const QVariant bz = stops.value( i ).toList().value( 0 );
2358 const QVariant bv = stops.value( i ).toList().value( 1 );
2359 if ( bv.type() != QVariant::List && bv.type() != QVariant::StringList )
2366 const QVariant tz = stops.value( i + 1 ).toList().value( 0 );
2367 const QVariant tv = stops.value( i + 1 ).toList().value( 1 );
2368 if ( tv.type() != QVariant::List && tv.type() != QVariant::StringList )
2374 caseString += QStringLiteral(
"WHEN @vector_tile_zoom > %1 AND @vector_tile_zoom <= %2 "
2375 "THEN array(%3,%4)" ).arg( bz.toString(),
2377 interpolateExpression( bz.toDouble(), tz.toDouble(), bv.toList().value( 0 ), tv.toList().value( 0 ), base, multiplier, &context ),
2378 interpolateExpression( bz.toDouble(), tz.toDouble(), bv.toList().value( 1 ), tv.toList().value( 1 ), base, multiplier, &context ) );
2380 caseString += QLatin1String(
"END" );
2386 if ( stops.length() < 2 )
2389 QString caseString = QStringLiteral(
"CASE " );
2391 for (
int i = 0; i < stops.length() - 1; ++i )
2394 const QVariant bz = stops.value( i ).toList().value( 0 );
2395 const QList<QVariant> bv = stops.value( i ).toList().value( 1 ).toList();
2398 for (
const QVariant &value : bv )
2400 const double number = value.toDouble( &ok );
2402 bl << QString::number( number * multiplier );
2406 const QVariant tz = stops.value( i + 1 ).toList().value( 0 );
2407 caseString += QStringLiteral(
"WHEN @vector_tile_zoom > %1 AND @vector_tile_zoom <= %2 "
2408 "THEN array(%3) " ).arg( bz.toString(),
2412 const QVariant lz = stops.value( stops.length() - 1 ).toList().value( 0 );
2413 const QList<QVariant> lv = stops.value( stops.length() - 1 ).toList().value( 1 ).toList();
2416 for (
const QVariant &value : lv )
2418 const double number = value.toDouble( &ok );
2420 ll << QString::number( number * multiplier );
2422 caseString += QStringLiteral(
"WHEN @vector_tile_zoom > %1 "
2423 "THEN array(%2) " ).arg( lz.toString(),
2425 caseString += QLatin1String(
"END" );
2431 QString caseString = QStringLiteral(
"CASE " );
2433 for (
int i = 0; i < stops.length() - 1; ++i )
2436 const QVariant bz = stops.value( i ).toList().value( 0 );
2437 const QVariant bv = stops.value( i ).toList().value( 1 );
2438 if ( bz.type() == QVariant::List || bz.type() == QVariant::StringList )
2440 context.
pushWarning( QObject::tr(
"%1: Expressions in interpolation function are not supported, skipping." ).arg( context.
layerId() ) );
2445 const QVariant tz = stops.value( i + 1 ).toList().value( 0 );
2446 const QVariant tv = stops.value( i + 1 ).toList().value( 1 );
2447 if ( tz.type() == QVariant::List || tz.type() == QVariant::StringList )
2449 context.
pushWarning( QObject::tr(
"%1: Expressions in interpolation function are not supported, skipping." ).arg( context.
layerId() ) );
2453 caseString += QStringLiteral(
"WHEN @vector_tile_zoom > %1 AND @vector_tile_zoom <= %2 "
2454 "THEN %3 " ).arg( bz.toString(),
2459 const QVariant z = stops.last().toList().value( 0 );
2460 const QVariant v = stops.last().toList().value( 1 );
2461 QString vStr = v.toString();
2462 if ( ( QMetaType::Type )v.type() == QMetaType::QVariantList )
2465 caseString += QStringLiteral(
"WHEN @vector_tile_zoom > %1 "
2466 "THEN ( ( %2 ) * %3 ) END" ).arg( z.toString() ).arg( vStr ).arg( multiplier );
2470 caseString += QStringLiteral(
"WHEN @vector_tile_zoom > %1 "
2471 "THEN %2 END" ).arg( z.toString() ).arg( v.toDouble() * multiplier );
2479 QString caseString = QStringLiteral(
"CASE " );
2481 for (
int i = 0; i < stops.length() - 1; ++i )
2484 const QVariant bz = stops.value( i ).toList().value( 0 );
2485 const QString bv = stops.value( i ).toList().value( 1 ).toString();
2486 if ( bz.type() == QVariant::List || bz.type() == QVariant::StringList )
2488 context.
pushWarning( QObject::tr(
"%1: Expressions in interpolation function are not supported, skipping." ).arg( context.
layerId() ) );
2493 const QVariant tz = stops.value( i + 1 ).toList().value( 0 );
2494 if ( tz.type() == QVariant::List || tz.type() == QVariant::StringList )
2496 context.
pushWarning( QObject::tr(
"%1: Expressions in interpolation function are not supported, skipping." ).arg( context.
layerId() ) );
2500 caseString += QStringLiteral(
"WHEN @vector_tile_zoom > %1 AND @vector_tile_zoom <= %2 "
2501 "THEN %3 " ).arg( bz.toString(),
2505 caseString += QStringLiteral(
"ELSE %1 END" ).arg(
QgsExpression::quotedValue( conversionMap.value( stops.constLast().toList().value( 1 ).toString(),
2506 stops.constLast().toList().value( 1 ) ) ) );
2507 if ( defaultString )
2508 *defaultString = stops.constLast().toList().value( 1 ).toString();
2514 QString caseString = QStringLiteral(
"CASE " );
2516 bool isExpression =
false;
2517 for (
int i = 0; i < stops.length() - 1; ++i )
2520 const QVariant bz = stops.value( i ).toList().value( 0 );
2521 if ( bz.type() == QVariant::List || bz.type() == QVariant::StringList )
2523 context.
pushWarning( QObject::tr(
"%1: Lists in label interpolation function are not supported, skipping." ).arg( context.
layerId() ) );
2528 const QVariant tz = stops.value( i + 1 ).toList().value( 0 );
2529 if ( tz.type() == QVariant::List || tz.type() == QVariant::StringList )
2531 context.
pushWarning( QObject::tr(
"%1: Lists in label interpolation function are not supported, skipping." ).arg( context.
layerId() ) );
2535 QString fieldPart = processLabelField( stops.constLast().toList().value( 1 ).toString(), isExpression );
2536 if ( fieldPart.isEmpty() )
2537 fieldPart = QStringLiteral(
"''" );
2538 else if ( !isExpression )
2541 caseString += QStringLiteral(
"WHEN @vector_tile_zoom > %1 AND @vector_tile_zoom < %2 "
2542 "THEN %3 " ).arg( bz.toString(),
2548 const QVariant bz = stops.constLast().toList().value( 0 );
2549 if ( bz.type() == QVariant::List || bz.type() == QVariant::StringList )
2551 context.
pushWarning( QObject::tr(
"%1: Lists in label interpolation function are not supported, skipping." ).arg( context.
layerId() ) );
2555 QString fieldPart = processLabelField( stops.constLast().toList().value( 1 ).toString(), isExpression );
2556 if ( fieldPart.isEmpty() )
2557 fieldPart = QStringLiteral(
"''" );
2558 else if ( !isExpression )
2561 caseString += QStringLiteral(
"WHEN @vector_tile_zoom >= %1 "
2562 "THEN %3 " ).arg( bz.toString(),
2566 QString defaultPart = processLabelField( stops.constFirst().toList().value( 1 ).toString(), isExpression );
2567 if ( defaultPart.isEmpty() )
2568 defaultPart = QStringLiteral(
"''" );
2569 else if ( !isExpression )
2571 caseString += QStringLiteral(
"ELSE %1 END" ).arg( defaultPart );
2578 const QString method = json.
value( 0 ).toString();
2579 if ( method == QLatin1String(
"interpolate" ) )
2583 else if ( method == QLatin1String(
"match" ) )
2585 return parseMatchList( json, type, context, multiplier, maxOpacity, defaultColor, defaultNumber );
2595 const QString attribute =
parseExpression( json.value( 1 ).toList(), context );
2596 if ( attribute.isEmpty() )
2598 context.
pushWarning( QObject::tr(
"%1: Could not interpret match list" ).arg( context.
layerId() ) );
2602 QString caseString = QStringLiteral(
"CASE " );
2604 for (
int i = 2; i < json.length() - 1; i += 2 )
2606 const QVariantList keys = json.value( i ).toList();
2608 QStringList matchString;
2609 for (
const QVariant &key : keys )
2614 const QVariant value = json.value( i + 1 );
2616 QString valueString;
2621 const QColor color =
parseColor( value, context );
2628 const double v = value.toDouble() * multiplier;
2629 valueString = QString::number( v );
2635 const double v = value.toDouble() * maxOpacity;
2636 valueString = QString::number( v );
2642 valueString = QStringLiteral(
"array(%1,%2)" ).arg( value.toList().value( 0 ).toDouble() * multiplier,
2643 value.toList().value( 0 ).toDouble() * multiplier );
2649 caseString += QStringLiteral(
"WHEN %1 IN (%2) THEN %3 " ).arg( attribute,
2650 matchString.join(
',' ), valueString );
2659 const QColor color =
parseColor( json.constLast(), context );
2661 *defaultColor = color;
2669 const double v = json.constLast().toDouble() * multiplier;
2670 if ( defaultNumber )
2672 elseValue = QString::number( v );
2678 const double v = json.constLast().toDouble() * maxOpacity;
2679 if ( defaultNumber )
2681 elseValue = QString::number( v );
2687 elseValue = QStringLiteral(
"array(%1,%2)" ).arg( json.constLast().toList().value( 0 ).toDouble() * multiplier,
2688 json.constLast().toList().value( 0 ).toDouble() * multiplier );
2694 caseString += QStringLiteral(
"ELSE %1 END" ).arg( elseValue );
2700 if ( json.value( 0 ).toString() != QLatin1String(
"interpolate" ) )
2702 context.
pushWarning( QObject::tr(
"%1: Could not interpret value list" ).arg( context.
layerId() ) );
2707 const QString technique = json.value( 1 ).toList().value( 0 ).toString();
2708 if ( technique == QLatin1String(
"linear" ) )
2710 else if ( technique == QLatin1String(
"exponential" ) )
2711 base = json.value( 1 ).toList(). value( 1 ).toDouble();
2712 else if ( technique == QLatin1String(
"cubic-bezier" ) )
2714 context.
pushWarning( QObject::tr(
"%1: Cubic-bezier interpolation is not supported, linear used instead." ).arg( context.
layerId() ) );
2719 context.
pushWarning( QObject::tr(
"%1: Skipping not implemented interpolation method %2" ).arg( context.
layerId(), technique ) );
2723 if ( json.value( 2 ).toList().value( 0 ).toString() != QLatin1String(
"zoom" ) )
2725 context.
pushWarning( QObject::tr(
"%1: Skipping not implemented interpolation input %2" ).arg( context.
layerId(), json.value( 2 ).toString() ) );
2731 for (
int i = 3; i < json.length(); i += 2 )
2733 stops.push_back( QVariantList() << json.value( i ).toString() << json.value( i + 1 ) );
2737 props.insert( QStringLiteral(
"stops" ), stops );
2738 props.insert( QStringLiteral(
"base" ), base );
2741 case PropertyType::Color:
2744 case PropertyType::Numeric:
2747 case PropertyType::Opacity:
2750 case PropertyType::Point:
2758 if ( ( QMetaType::Type )colorExpression.type() == QMetaType::QVariantList )
2762 return parseValue( colorExpression, context,
true );
2767 if ( color.type() != QVariant::String )
2769 context.
pushWarning( QObject::tr(
"%1: Could not parse non-string color %2, skipping" ).arg( context.
layerId(), color.toString() ) );
2778 hue = std::max( 0, color.hslHue() );
2779 saturation = color.hslSaturation() / 255.0 * 100;
2780 lightness = color.lightness() / 255.0 * 100;
2781 alpha = color.alpha();
2789 context = *contextPtr;
2793 if ( valueMin.canConvert( QMetaType::Double ) && valueMax.canConvert( QMetaType::Double ) )
2795 bool minDoubleOk =
true;
2796 const double min = valueMin.toDouble( &minDoubleOk );
2797 bool maxDoubleOk =
true;
2798 const double max = valueMax.toDouble( &maxDoubleOk );
2799 if ( minDoubleOk && maxDoubleOk &&
qgsDoubleNear( min, max ) )
2801 return QString::number( min * multiplier );
2805 QString minValueExpr = valueMin.toString();
2806 QString maxValueExpr = valueMax.toString();
2807 if ( ( QMetaType::Type )valueMin.type() == QMetaType::QVariantList )
2811 if ( ( QMetaType::Type )valueMax.type() == QMetaType::QVariantList )
2816 if ( minValueExpr == maxValueExpr )
2818 return minValueExpr;
2824 expression = QStringLiteral(
"scale_linear(@vector_tile_zoom,%1,%2,%3,%4)" ).arg( zoomMin )
2826 .arg( minValueExpr )
2827 .arg( maxValueExpr );
2831 expression = QStringLiteral(
"scale_exp(@vector_tile_zoom,%1,%2,%3,%4,%5)" ).arg( zoomMin )
2833 .arg( minValueExpr )
2834 .arg( maxValueExpr )
2838 if ( multiplier != 1 )
2839 return QStringLiteral(
"%1 * %2" ).arg( expression ).arg( multiplier );
2846 if ( style == QLatin1String(
"round" ) )
2847 return Qt::RoundCap;
2848 else if ( style == QLatin1String(
"square" ) )
2849 return Qt::SquareCap;
2856 if ( style == QLatin1String(
"bevel" ) )
2857 return Qt::BevelJoin;
2858 else if ( style == QLatin1String(
"round" ) )
2859 return Qt::RoundJoin;
2861 return Qt::MiterJoin;
2866 QString op = expression.value( 0 ).toString();
2867 if ( op == QLatin1String(
"%" ) && expression.size() >= 3 )
2869 return QStringLiteral(
"%1 %2 %3" ).arg( parseValue( expression.value( 1 ), context ) ).arg( op ).arg( parseValue( expression.value( 2 ), context ) );
2871 else if ( op == QLatin1String(
"to-number" ) )
2873 return QStringLiteral(
"to_real(%1)" ).arg( parseValue( expression.value( 1 ), context ) );
2875 if ( op == QLatin1String(
"literal" ) )
2877 return expression.value( 1 ).toString();
2879 else if ( op == QLatin1String(
"all" )
2880 || op == QLatin1String(
"any" )
2881 || op == QLatin1String(
"none" ) )
2884 for (
int i = 1; i < expression.size(); ++i )
2886 const QString part = parseValue( expression.at( i ), context );
2887 if ( part.isEmpty() )
2889 context.
pushWarning( QObject::tr(
"%1: Skipping unsupported expression" ).arg( context.
layerId() ) );
2895 if ( op == QLatin1String(
"none" ) )
2896 return QStringLiteral(
"NOT (%1)" ).arg( parts.join( QLatin1String(
") AND NOT (" ) ) );
2898 QString operatorString;
2899 if ( op == QLatin1String(
"all" ) )
2900 operatorString = QStringLiteral(
") AND (" );
2901 else if ( op == QLatin1String(
"any" ) )
2902 operatorString = QStringLiteral(
") OR (" );
2904 return QStringLiteral(
"(%1)" ).arg( parts.join( operatorString ) );
2906 else if ( op ==
'!' )
2909 QVariantList contraJsonExpr = expression.value( 1 ).toList();
2910 contraJsonExpr[0] = QString( op + contraJsonExpr[0].toString() );
2912 return parseKey( contraJsonExpr, context );
2914 else if ( op == QLatin1String(
"==" )
2915 || op == QLatin1String(
"!=" )
2916 || op == QLatin1String(
">=" )
2918 || op == QLatin1String(
"<=" )
2922 if ( op == QLatin1String(
"==" ) )
2923 op = QStringLiteral(
"IS" );
2924 else if ( op == QLatin1String(
"!=" ) )
2925 op = QStringLiteral(
"IS NOT" );
2926 return QStringLiteral(
"%1 %2 %3" ).arg( parseKey( expression.value( 1 ), context ),
2927 op, parseValue( expression.value( 2 ), context ) );
2929 else if ( op == QLatin1String(
"has" ) )
2931 return parseKey( expression.value( 1 ), context ) + QStringLiteral(
" IS NOT NULL" );
2933 else if ( op == QLatin1String(
"!has" ) )
2935 return parseKey( expression.value( 1 ), context ) + QStringLiteral(
" IS NULL" );
2937 else if ( op == QLatin1String(
"in" ) || op == QLatin1String(
"!in" ) )
2939 const QString key = parseKey( expression.value( 1 ), context );
2941 for (
int i = 2; i < expression.size(); ++i )
2943 const QString part = parseValue( expression.at( i ), context );
2944 if ( part.isEmpty() )
2946 context.
pushWarning( QObject::tr(
"%1: Skipping unsupported expression" ).arg( context.
layerId() ) );
2951 if ( op == QLatin1String(
"in" ) )
2952 return QStringLiteral(
"%1 IN (%2)" ).arg( key, parts.join( QLatin1String(
", " ) ) );
2954 return QStringLiteral(
"(%1 IS NULL OR %1 NOT IN (%2))" ).arg( key, parts.join( QLatin1String(
", " ) ) );
2956 else if ( op == QLatin1String(
"get" ) )
2958 return parseKey( expression.value( 1 ), context );
2960 else if ( op == QLatin1String(
"match" ) )
2962 const QString attribute = expression.value( 1 ).toList().value( 1 ).toString();
2964 if ( expression.size() == 5
2965 && expression.at( 3 ).type() == QVariant::Bool && expression.at( 3 ).toBool() ==
true
2966 && expression.at( 4 ).type() == QVariant::Bool && expression.at( 4 ).toBool() ==
false )
2969 if ( expression.at( 2 ).type() == QVariant::List || expression.at( 2 ).type() == QVariant::StringList )
2972 for (
const QVariant &p : expression.at( 2 ).toList() )
2974 parts << parseValue( p, context );
2977 if ( parts.size() > 1 )
2982 else if ( expression.at( 2 ).type() == QVariant::String || expression.at( 2 ).type() == QVariant::Int
2983 || expression.at( 2 ).type() == QVariant::Double )
2989 context.
pushWarning( QObject::tr(
"%1: Skipping unsupported expression" ).arg( context.
layerId() ) );
2995 QString caseString = QStringLiteral(
"CASE " );
2996 for (
int i = 2; i < expression.size() - 2; i += 2 )
2998 if ( expression.at( i ).type() == QVariant::List || expression.at( i ).type() == QVariant::StringList )
3001 for (
const QVariant &p : expression.at( i ).toList() )
3006 if ( parts.size() > 1 )
3011 else if ( expression.at( i ).type() == QVariant::String || expression.at( i ).type() == QVariant::Int
3012 || expression.at( i ).type() == QVariant::Double )
3017 caseString += QStringLiteral(
"THEN %1 " ).arg( parseValue( expression.at( i + 1 ), context, colorExpected ) );
3019 caseString += QStringLiteral(
"ELSE %1 END" ).arg( parseValue( expression.last(), context, colorExpected ) );
3023 else if ( op == QLatin1String(
"to-string" ) )
3025 return QStringLiteral(
"to_string(%1)" ).arg(
parseExpression( expression.value( 1 ).toList(), context ) );
3029 context.
pushWarning( QObject::tr(
"%1: Skipping unsupported expression" ).arg( context.
layerId() ) );
3038 context.
pushWarning( QObject::tr(
"%1: Could not retrieve sprite '%2'" ).arg( context.
layerId(), name ) );
3042 const QVariantMap spriteDefinition = context.
spriteDefinitions().value( name ).toMap();
3043 if ( spriteDefinition.size() == 0 )
3045 context.
pushWarning( QObject::tr(
"%1: Could not retrieve sprite '%2'" ).arg( context.
layerId(), name ) );
3049 const QImage sprite = context.
spriteImage().copy( spriteDefinition.value( QStringLiteral(
"x" ) ).toInt(),
3050 spriteDefinition.value( QStringLiteral(
"y" ) ).toInt(),
3051 spriteDefinition.value( QStringLiteral(
"width" ) ).toInt(),
3052 spriteDefinition.value( QStringLiteral(
"height" ) ).toInt() );
3053 if ( sprite.isNull() )
3055 context.
pushWarning( QObject::tr(
"%1: Could not retrieve sprite '%2'" ).arg( context.
layerId(), name ) );
3059 spriteSize = sprite.size() / spriteDefinition.value( QStringLiteral(
"pixelRatio" ) ).toDouble() * context.
pixelSizeConversionFactor();
3067 auto prepareBase64 = [](
const QImage & sprite )
3070 if ( !sprite.isNull() )
3073 QBuffer buffer( &blob );
3074 buffer.open( QIODevice::WriteOnly );
3075 sprite.save( &buffer,
"PNG" );
3077 const QByteArray encoded = blob.toBase64();
3078 path = QString( encoded );
3079 path.prepend( QLatin1String(
"base64:" ) );
3084 switch ( value.type() )
3086 case QVariant::String:
3088 QString spriteName = value.toString();
3089 const QRegularExpression fieldNameMatch( QStringLiteral(
"{([^}]+)}" ) );
3090 QRegularExpressionMatch match = fieldNameMatch.match( spriteName );
3091 if ( match.hasMatch() )
3093 const QString fieldName = match.captured( 1 );
3094 spriteProperty = QStringLiteral(
"CASE" );
3095 spriteSizeProperty = QStringLiteral(
"CASE" );
3097 spriteName.replace(
"(", QLatin1String(
"\\(" ) );
3098 spriteName.replace(
")", QLatin1String(
"\\)" ) );
3099 spriteName.replace( fieldNameMatch, QStringLiteral(
"([^\\/\\\\]+)" ) );
3100 const QRegularExpression fieldValueMatch( spriteName );
3102 for (
const QString &name : spriteNames )
3104 match = fieldValueMatch.match( name );
3105 if ( match.hasMatch() )
3109 const QString fieldValue = match.captured( 1 );
3111 path = prepareBase64( sprite );
3112 if ( spritePath.isEmpty() && !path.isEmpty() )
3118 spriteProperty += QStringLiteral(
" WHEN \"%1\" = '%2' THEN '%3'" )
3119 .arg( fieldName, fieldValue, path );
3120 spriteSizeProperty += QStringLiteral(
" WHEN \"%1\" = '%2' THEN %3" )
3121 .arg( fieldName ).arg( fieldValue ).arg( size.width() );
3125 spriteProperty += QLatin1String(
" END" );
3126 spriteSizeProperty += QLatin1String(
" END" );
3130 spriteProperty.clear();
3131 spriteSizeProperty.clear();
3132 const QImage sprite =
retrieveSprite( spriteName, context, spriteSize );
3133 spritePath = prepareBase64( sprite );
3140 const QVariantList stops = value.toMap().value( QStringLiteral(
"stops" ) ).toList();
3141 if ( stops.size() == 0 )
3148 sprite =
retrieveSprite( stops.value( 0 ).toList().value( 1 ).toString(), context, spriteSize );
3149 spritePath = prepareBase64( sprite );
3151 spriteProperty = QStringLiteral(
"CASE WHEN @vector_tile_zoom < %1 THEN '%2'" )
3152 .arg( stops.value( 0 ).toList().value( 0 ).toString() )
3154 spriteSizeProperty = QStringLiteral(
"CASE WHEN @vector_tile_zoom < %1 THEN %2" )
3155 .arg( stops.value( 0 ).toList().value( 0 ).toString() )
3156 .arg( spriteSize.width() );
3158 for (
int i = 0; i < stops.size() - 1; ++i )
3161 sprite =
retrieveSprite( stops.value( 0 ).toList().value( 1 ).toString(), context, size );
3162 path = prepareBase64( sprite );
3164 spriteProperty += QStringLiteral(
" WHEN @vector_tile_zoom >= %1 AND @vector_tile_zoom < %2 "
3166 .arg( stops.value( i ).toList().value( 0 ).toString(),
3167 stops.value( i + 1 ).toList().value( 0 ).toString(),
3169 spriteSizeProperty += QStringLiteral(
" WHEN @vector_tile_zoom >= %1 AND @vector_tile_zoom < %2 "
3171 .arg( stops.value( i ).toList().value( 0 ).toString(),
3172 stops.value( i + 1 ).toList().value( 0 ).toString() )
3173 .arg( size.width() );
3175 sprite =
retrieveSprite( stops.last().toList().value( 1 ).toString(), context, size );
3176 path = prepareBase64( sprite );
3178 spriteProperty += QStringLiteral(
" WHEN @vector_tile_zoom >= %1 "
3180 .arg( stops.last().toList().value( 0 ).toString() )
3182 spriteSizeProperty += QStringLiteral(
" WHEN @vector_tile_zoom >= %1 "
3184 .arg( stops.last().toList().value( 0 ).toString() )
3185 .arg( size.width() );
3189 case QVariant::List:
3191 const QVariantList json = value.toList();
3192 const QString method = json.value( 0 ).toString();
3193 if ( method != QLatin1String(
"match" ) )
3195 context.
pushWarning( QObject::tr(
"%1: Could not interpret sprite value list with method %2" ).arg( context.
layerId(), method ) );
3199 const QString attribute =
parseExpression( json.value( 1 ).toList(), context );
3200 if ( attribute.isEmpty() )
3202 context.
pushWarning( QObject::tr(
"%1: Could not interpret match list" ).arg( context.
layerId() ) );
3206 spriteProperty = QStringLiteral(
"CASE " );
3207 spriteSizeProperty = QStringLiteral(
"CASE " );
3209 for (
int i = 2; i < json.length() - 1; i += 2 )
3211 const QVariantList keys = json.value( i ).toList();
3213 QStringList matchString;
3214 for (
const QVariant &key : keys )
3219 const QVariant value = json.value( i + 1 );
3221 const QImage sprite =
retrieveSprite( value.toString(), context, spriteSize );
3222 spritePath = prepareBase64( sprite );
3224 spriteProperty += QStringLiteral(
" WHEN %1 IN (%2) "
3225 "THEN '%3' " ).arg( attribute,
3226 matchString.join(
',' ),
3229 spriteSizeProperty += QStringLiteral(
" WHEN %1 IN (%2) "
3230 "THEN %3 " ).arg( attribute,
3231 matchString.join(
',' ) ).arg( spriteSize.width() );
3234 const QImage sprite =
retrieveSprite( json.constLast().toString(), context, spriteSize );
3235 spritePath = prepareBase64( sprite );
3237 spriteProperty += QStringLiteral(
"ELSE %1 END" ).arg( spritePath );
3238 spriteSizeProperty += QStringLiteral(
"ELSE %3 END" ).arg( spriteSize.width() );
3253 switch ( value.type() )
3255 case QVariant::List:
3256 case QVariant::StringList:
3259 case QVariant::Bool:
3260 case QVariant::String:
3261 if ( colorExpected )
3266 return parseValue(
c, context );
3272 case QVariant::Double:
3273 return value.toString();
3275 case QVariant::Color:
3276 c = value.value<QColor>();
3277 return QString(
"color_rgba(%1,%2,%3,%4)" ).arg(
c.red() ).arg(
c.green() ).arg(
c.blue() ).arg(
c.alpha() );
3280 context.
pushWarning( QObject::tr(
"%1: Skipping unsupported expression part" ).arg( context.
layerId() ) );
3288 if ( value.toString() == QLatin1String(
"$type" ) )
3290 return QStringLiteral(
"_geom_type" );
3292 if ( value.toString() == QLatin1String(
"level" ) )
3294 return QStringLiteral(
"level" );
3296 else if ( ( value.type() == QVariant::List && value.toList().size() == 1 ) || value.type() == QVariant::StringList )
3298 if ( value.toList().size() > 1 )
3299 return value.toList().at( 1 ).toString();
3302 QString valueString = value.toList().value( 0 ).toString();
3303 if ( valueString == QLatin1String(
"geometry-type" ) )
3305 return QStringLiteral(
"_geom_type" );
3310 else if ( value.type() == QVariant::List && value.toList().size() > 1 )
3317 QString QgsMapBoxGlStyleConverter::processLabelField(
const QString &
string,
bool &isExpression )
3321 const QRegularExpression singleFieldRx( QStringLiteral(
"^{([^}]+)}$" ) );
3322 const QRegularExpressionMatch match = singleFieldRx.match(
string );
3323 if ( match.hasMatch() )
3325 isExpression =
false;
3326 return match.captured( 1 );
3329 const QRegularExpression multiFieldRx( QStringLiteral(
"(?={[^}]+})" ) );
3330 const QStringList parts =
string.split( multiFieldRx );
3331 if ( parts.size() > 1 )
3333 isExpression =
true;
3336 for (
const QString &part : parts )
3338 if ( part.isEmpty() )
3341 if ( !part.contains(
'{' ) )
3348 const QStringList split = part.split(
'}' );
3350 if ( !split.at( 1 ).isEmpty() )
3353 return QStringLiteral(
"concat(%1)" ).arg( res.join(
',' ) );
3357 isExpression =
false;
3364 return mRenderer ? mRenderer->clone() :
nullptr;
3369 return mLabeling ? mLabeling->clone() :
nullptr;
3372 bool QgsMapBoxGlStyleConverter::numericArgumentsOnly(
const QVariant &bottomVariant,
const QVariant &topVariant,
double &bottom,
double &top )
3374 if ( bottomVariant.canConvert( QMetaType::Double ) && topVariant.canConvert( QMetaType::Double ) )
3376 bool bDoubleOk, tDoubleOk;
3377 bottom = bottomVariant.toDouble( &bDoubleOk );
3378 top = topVariant.toDouble( &tDoubleOk );
3379 return ( bDoubleOk && tDoubleOk );
3390 mWarnings << warning;
3405 return mSizeConversionFactor;
3410 mSizeConversionFactor = sizeConversionFactor;
3415 return mSpriteImage;
3420 return mSpriteDefinitions;
3425 mSpriteImage = image;
3426 mSpriteDefinitions = definitions;
@ CentralPoint
Place symbols at the mid point of the line.
@ OverPoint
Arranges candidates over a point (or centroid of a polygon), or at a preset offset from the point....
@ 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...
@ Viewport
Relative to the whole viewport/output device.
void setPenJoinStyle(Qt::PenJoinStyle style)
Sets the pen join style used to render the line (e.g.
void setPenCapStyle(Qt::PenCapStyle style)
Sets the pen cap style used to render the line (e.g.
static QgsFontManager * fontManager()
Returns the application font manager, which manages available fonts and font installation for the QGI...
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, QVariant::Type fieldType=QVariant::Type::Invalid)
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)
QString processFontFamilyName(const QString &name) const
Processes a font family name, applying any matching fontFamilyReplacements() to the name.
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 and ...
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 parseOpacityStops(double base, const QVariantList &stops, int maxOpacity, QgsMapBoxGlStyleConversionContext &context)
Takes values from stops and uses either scale_linear() or scale_exp() functions to interpolate alpha ...
static QString parseColorExpression(const QVariant &colorExpression, QgsMapBoxGlStyleConversionContext &context)
Converts an expression representing a color to a string (can be color string or an expression where a...
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 QString parseExpression(const QVariantList &expression, QgsMapBoxGlStyleConversionContext &context, bool colorExpected=false)
Converts a MapBox GL expression to a QGIS expression.
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 QString interpolateExpression(double zoomMin, double zoomMax, QVariant valueMin, QVariant valueMax, double base, double multiplier=1, QgsMapBoxGlStyleConversionContext *contextPtr=0)
Generates an interpolation for values between valueMin and valueMax, scaled between the ranges zoomMi...
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.
static QString parseLabelStops(const QVariantList &stops, QgsMapBoxGlStyleConversionContext &context)
Parses a list of interpolation stops containing label values.
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 QgsProperty parseInterpolateOpacityByZoom(const QVariantMap &json, int maxOpacity, QgsMapBoxGlStyleConversionContext *contextPtr=0)
Interpolates opacity with either scale_linear() or scale_exp() (depending on base value).
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 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 bool parseFillLayer(const QVariantMap &jsonLayer, QgsVectorTileBasicRendererStyle &style, QgsMapBoxGlStyleConversionContext &context, bool isBackgroundStyle=false)
Parses a fill layer.
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 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 parseStringStops(const QVariantList &stops, QgsMapBoxGlStyleConversionContext &context, const QVariantMap &conversionMap, QString *defaultString=nullptr)
Parses a list of interpolation stops containing string values.
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 parseArrayStops(const QVariantList &stops, QgsMapBoxGlStyleConversionContext &context, double multiplier=1)
Takes numerical arrays from stops.
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.
Qgis::LabelPlacement placement
Label placement mode.
QgsUnitTypes::RenderUnit offsetUnits
Units for offsets of label.
Qgis::LabelQuadrantPosition quadOffset
Sets the quadrant in which to offset labels from feature.
Qgis::LabelMultiLineAlignment multilineAlign
Horizontal alignment of multi-line labels.
int priority
Label priority.
QgsUnitTypes::RenderUnit distUnits
Units the distance from feature to the label.
@ 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.
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(Qgis::SymbolCoordinateReference mode)
Set the coordinate mode for fill.
Line symbol layer type which draws line sections using a raster image file.
void setOutputUnit(QgsUnitTypes::RenderUnit unit) override
Sets the units to use for sizes and widths within the symbol layer.
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
Sets the fill color for the symbol layer.
void setOffset(QPointF offset)
Sets an offset by which polygons will be translated during rendering.
void setStrokeColor(const QColor &strokeColor) override
Sets the stroke color for the symbol layer.
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
Sets the fill color for the symbol layer.
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.
@ PropertyCustomDash
Custom dash pattern.
@ 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)
Sets the "representative" color for the symbol layer.
void setDataDefinedProperties(const QgsPropertyCollection &collection)
Sets the symbol layer's property collection, used for data defined overrides.
@ PropertyOpacity
Opacity.
void setPlacements(Qgis::MarkerLinePlacements placements)
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.
void setNamedStyle(const QString &style)
Sets the named style for the font used for rendering text.
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.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QList< QgsSymbolLayer * > QgsSymbolLayerList