Skip to content
Permalink
Browse files
[vectortile] Support the 'background' concept for vector tile rendering
  • Loading branch information
nirvn authored and nyalldawson committed Nov 14, 2021
1 parent 0fcdb59 commit 914cf37217f216a1fba79b3d176692f16f686d17
@@ -243,7 +243,7 @@ Parse list of ``layers`` from JSON.
This is private API only, and may change in future QGIS versions
%End

static bool parseFillLayer( const QVariantMap &jsonLayer, QgsVectorTileBasicRendererStyle &style /Out/, QgsMapBoxGlStyleConversionContext &context );
static bool parseFillLayer( const QVariantMap &jsonLayer, QgsVectorTileBasicRendererStyle &style /Out/, QgsMapBoxGlStyleConversionContext &context, bool isBackgroundStyle = false );
%Docstring
Parses a fill layer.

@@ -253,6 +253,7 @@ Parses a fill layer.

:param jsonLayer: fill layer to parse
:param context: conversion context
:param isBackgroundStyle: set to ``True`` if the layer should be parsed as background layer

:return: - ``True`` if the layer was successfully parsed.
- style: generated QGIS vector tile style
@@ -79,13 +79,26 @@ void QgsMapBoxGlStyleConverter::parseLayers( const QVariantList &layers, QgsMapB
QList<QgsVectorTileBasicRendererStyle> rendererStyles;
QList<QgsVectorTileBasicLabelingStyle> labelingStyles;

QgsVectorTileBasicRendererStyle rendererBackgroundStyle;
bool hasRendererBackgroundStyle = false;

for ( const QVariant &layer : layers )
{
const QVariantMap jsonLayer = layer.toMap();

const QString layerType = jsonLayer.value( QStringLiteral( "type" ) ).toString();
if ( layerType == QLatin1String( "background" ) )
{
hasRendererBackgroundStyle = parseFillLayer( jsonLayer, rendererBackgroundStyle, *context, true );
if ( hasRendererBackgroundStyle )
{
rendererBackgroundStyle.setStyleName( layerType );
rendererBackgroundStyle.setLayerName( layerType );
rendererBackgroundStyle.setFilterExpression( QString() );
rendererBackgroundStyle.setEnabled( true );
}
continue;
}

const QString styleId = jsonLayer.value( QStringLiteral( "id" ) ).toString();
context->setLayerId( styleId );
@@ -156,6 +169,9 @@ void QgsMapBoxGlStyleConverter::parseLayers( const QVariantList &layers, QgsMapB
context->clearWarnings();
}

if ( hasRendererBackgroundStyle )
rendererStyles.prepend( rendererBackgroundStyle );

mRenderer = std::make_unique< QgsVectorTileBasicRenderer >();
QgsVectorTileBasicRenderer *renderer = dynamic_cast< QgsVectorTileBasicRenderer *>( mRenderer.get() );
renderer->setStyles( rendererStyles );
@@ -165,7 +181,7 @@ void QgsMapBoxGlStyleConverter::parseLayers( const QVariantList &layers, QgsMapB
labeling->setStyles( labelingStyles );
}

bool QgsMapBoxGlStyleConverter::parseFillLayer( const QVariantMap &jsonLayer, QgsVectorTileBasicRendererStyle &style, QgsMapBoxGlStyleConversionContext &context )
bool QgsMapBoxGlStyleConverter::parseFillLayer( const QVariantMap &jsonLayer, QgsVectorTileBasicRendererStyle &style, QgsMapBoxGlStyleConversionContext &context, bool isBackgroundStyle )
{
if ( !jsonLayer.contains( QStringLiteral( "paint" ) ) )
{
@@ -180,9 +196,9 @@ bool QgsMapBoxGlStyleConverter::parseFillLayer( const QVariantMap &jsonLayer, Qg

// fill color
QColor fillColor;
if ( jsonPaint.contains( QStringLiteral( "fill-color" ) ) )
if ( jsonPaint.contains( isBackgroundStyle ? QStringLiteral( "background-color" ) : QStringLiteral( "fill-color" ) ) )
{
const QVariant jsonFillColor = jsonPaint.value( QStringLiteral( "fill-color" ) );
const QVariant jsonFillColor = jsonPaint.value( isBackgroundStyle ? QStringLiteral( "background-color" ) : QStringLiteral( "fill-color" ) );
switch ( jsonFillColor.type() )
{
case QVariant::Map:
@@ -212,7 +228,7 @@ bool QgsMapBoxGlStyleConverter::parseFillLayer( const QVariantMap &jsonLayer, Qg
}

QColor fillOutlineColor;
if ( !jsonPaint.contains( QStringLiteral( "fill-outline-color" ) ) )
if ( !isBackgroundStyle && !jsonPaint.contains( QStringLiteral( "fill-outline-color" ) ) )
{
// fill-outline-color
if ( fillColor.isValid() )
@@ -250,9 +266,9 @@ bool QgsMapBoxGlStyleConverter::parseFillLayer( const QVariantMap &jsonLayer, Qg

double fillOpacity = -1.0;
double rasterOpacity = -1.0;
if ( jsonPaint.contains( QStringLiteral( "fill-opacity" ) ) )
if ( jsonPaint.contains( isBackgroundStyle ? QStringLiteral( "background-opacity" ) : QStringLiteral( "fill-opacity" ) ) )
{
const QVariant jsonFillOpacity = jsonPaint.value( QStringLiteral( "fill-opacity" ) );
const QVariant jsonFillOpacity = jsonPaint.value( isBackgroundStyle ? QStringLiteral( "background-opacity" ) : QStringLiteral( "fill-opacity" ) );
switch ( jsonFillOpacity.type() )
{
case QVariant::Int:
@@ -332,11 +348,11 @@ bool QgsMapBoxGlStyleConverter::parseFillLayer( const QVariantMap &jsonLayer, Qg
}
fillSymbol->setOffsetUnit( context.targetUnit() );

if ( jsonPaint.contains( QStringLiteral( "fill-pattern" ) ) )
if ( jsonPaint.contains( isBackgroundStyle ? QStringLiteral( "background-pattern" ) : QStringLiteral( "fill-pattern" ) ) )
{
// get fill-pattern to set sprite

const QVariant fillPatternJson = jsonPaint.value( QStringLiteral( "fill-pattern" ) );
const QVariant fillPatternJson = jsonPaint.value( isBackgroundStyle ? QStringLiteral( "background-pattern" ) : QStringLiteral( "fill-pattern" ) );

// fill-pattern disabled dillcolor
fillColor = QColor();
@@ -273,9 +273,10 @@ class CORE_EXPORT QgsMapBoxGlStyleConverter
* \param jsonLayer fill layer to parse
* \param style generated QGIS vector tile style
* \param context conversion context
* \param isBackgroundStyle set to TRUE if the layer should be parsed as background layer
* \returns TRUE if the layer was successfully parsed.
*/
static bool parseFillLayer( const QVariantMap &jsonLayer, QgsVectorTileBasicRendererStyle &style SIP_OUT, QgsMapBoxGlStyleConversionContext &context );
static bool parseFillLayer( const QVariantMap &jsonLayer, QgsVectorTileBasicRendererStyle &style SIP_OUT, QgsMapBoxGlStyleConversionContext &context, bool isBackgroundStyle = false );

/**
* Parses a line layer.
@@ -182,7 +182,13 @@ void QgsVectorTileBasicRenderer::renderTile( const QgsVectorTileRendererData &ti

QgsSymbol *sym = layerStyle.symbol();
sym->startRender( context, QgsFields() );
if ( layerStyle.layerName().isEmpty() )
if ( layerStyle.layerName() == QLatin1String( "background" ) )
{
QgsFillSymbol *fillSym = dynamic_cast<QgsFillSymbol *>( sym );
if ( fillSym )
fillSym->renderPolygon( tile.tilePolygon(), nullptr, nullptr, context );
}
else if ( layerStyle.layerName().isEmpty() )
{
// matching all layers
for ( QString layerName : tileData.keys() )
@@ -28,6 +28,8 @@
#include "qgsfontutils.h"
#include "qgslinesymbollayer.h"
#include "qgslinesymbol.h"
#include "qgsfillsymbollayer.h"
#include "qgsfillsymbol.h"

/**
* \ingroup UnitTests
@@ -259,8 +261,6 @@ void TestQgsVectorTileLayer::test_polygonWithLineStyle()
const QColor lineStrokeColor = Qt::blue;
const double lineStrokeWidth = DEFAULT_LINE_WIDTH * 2;

QgsVectorTileBasicRenderer *rend = new QgsVectorTileBasicRenderer;

QgsSimpleLineSymbolLayer *lineSymbolLayer = new QgsSimpleLineSymbolLayer;
lineSymbolLayer->setColor( lineStrokeColor );
lineSymbolLayer->setWidth( lineStrokeWidth );
@@ -269,7 +269,16 @@ void TestQgsVectorTileLayer::test_polygonWithLineStyle()
QgsVectorTileBasicRendererStyle st( QStringLiteral( "Polygons" ), QString(), QgsWkbTypes::LineGeometry );
st.setSymbol( lineSymbol );

rend->setStyles( QList<QgsVectorTileBasicRendererStyle>() << st );
QgsSimpleFillSymbolLayer *fillSymbolLayer = new QgsSimpleFillSymbolLayer;
fillSymbolLayer->setColor( Qt::white );
fillSymbolLayer->setStrokeStyle( Qt::NoPen );
QgsFillSymbol *fillSymbol = new QgsFillSymbol( QgsSymbolLayerList() << fillSymbolLayer );

QgsVectorTileBasicRendererStyle bgst( QStringLiteral( "background" ), QStringLiteral( "background" ), QgsWkbTypes::PolygonGeometry );
bgst.setSymbol( fillSymbol );

QgsVectorTileBasicRenderer *rend = new QgsVectorTileBasicRenderer;
rend->setStyles( QList<QgsVectorTileBasicRendererStyle>() << bgst << st );
layer->setRenderer( rend ); // takes ownership

QVERIFY( imageCheck( "render_test_polygon_with_line_style", layer.get(), layer->extent() ) );
Binary file not shown.

0 comments on commit 914cf37

Please sign in to comment.