Skip to content

Commit

Permalink
Move loading MVT sprites to utils class and use it from QgsVectorTile…
Browse files Browse the repository at this point in the history
…LayerProperties and QgsVectorTileLayer
  • Loading branch information
mhugent authored and nyalldawson committed Apr 10, 2023
1 parent db705c9 commit a336a23
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 63 deletions.
63 changes: 1 addition & 62 deletions src/core/vectortile/qgsvectortilelayer.cpp
Expand Up @@ -429,68 +429,7 @@ bool QgsVectorTileLayer::loadDefaultStyleAndSubLayersPrivate( QString &error, QS
styleDefinition = QgsJsonUtils::parseJson( content.content() ).toMap();
}

if ( styleDefinition.contains( QStringLiteral( "sprite" ) ) && ( context.spriteDefinitions().empty() || context.spriteImage().isNull() ) )
{
// retrieve sprite definition
QString spriteUriBase;
if ( styleDefinition.value( QStringLiteral( "sprite" ) ).toString().startsWith( QLatin1String( "http" ) ) )
{
spriteUriBase = styleDefinition.value( QStringLiteral( "sprite" ) ).toString();
}
else
{
spriteUriBase = styleUrl + '/' + styleDefinition.value( QStringLiteral( "sprite" ) ).toString();
}

for ( int resolution = 2; resolution > 0; resolution-- )
{
QUrl spriteUrl = QUrl( spriteUriBase );
spriteUrl.setPath( spriteUrl.path() + QStringLiteral( "%1.json" ).arg( resolution > 1 ? QStringLiteral( "@%1x" ).arg( resolution ) : QString() ) );
QNetworkRequest request = QNetworkRequest( spriteUrl );
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsVectorTileLayer" ) )
QgsBlockingNetworkRequest networkRequest;
switch ( networkRequest.get( request ) )
{
case QgsBlockingNetworkRequest::NoError:
{
const QgsNetworkReplyContent content = networkRequest.reply();
const QVariantMap spriteDefinition = QgsJsonUtils::parseJson( content.content() ).toMap();

// retrieve sprite images
QUrl spriteUrl = QUrl( spriteUriBase );
spriteUrl.setPath( spriteUrl.path() + QStringLiteral( "%1.png" ).arg( resolution > 1 ? QStringLiteral( "@%1x" ).arg( resolution ) : QString() ) );
QNetworkRequest request = QNetworkRequest( spriteUrl );
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsVectorTileLayer" ) )
QgsBlockingNetworkRequest networkRequest;
switch ( networkRequest.get( request ) )
{
case QgsBlockingNetworkRequest::NoError:
{
const QgsNetworkReplyContent imageContent = networkRequest.reply();
const QImage spriteImage( QImage::fromData( imageContent.content() ) );
context.setSprites( spriteImage, spriteDefinition );
break;
}

case QgsBlockingNetworkRequest::NetworkError:
case QgsBlockingNetworkRequest::TimeoutError:
case QgsBlockingNetworkRequest::ServerExceptionError:
break;
}

break;
}

case QgsBlockingNetworkRequest::NetworkError:
case QgsBlockingNetworkRequest::TimeoutError:
case QgsBlockingNetworkRequest::ServerExceptionError:
break;
}

if ( !context.spriteDefinitions().isEmpty() )
break;
}
}
QgsVectorTileUtils::loadSprites( styleDefinition, context, styleUrl );
}

if ( !styleDefinition.isEmpty() )
Expand Down
72 changes: 71 additions & 1 deletion src/core/vectortile/qgsvectortileutils.cpp
Expand Up @@ -30,7 +30,10 @@
#include "qgsvectortilemvtdecoder.h"
#include "qgsvectortilelayer.h"
#include "qgsvectortilerenderer.h"

#include "qgsmapboxglstyleconverter.h"
#include "qgsnetworkaccessmanager.h"
#include "qgsblockingnetworkrequest.h"
#include "qgsjsonutils.h"


QPolygon QgsVectorTileUtils::tilePolygon( QgsTileXYZ id, const QgsCoordinateTransform &ct, const QgsTileMatrix &tm, const QgsMapToPixel &mtp )
Expand Down Expand Up @@ -179,3 +182,70 @@ void QgsVectorTileUtils::sortTilesByDistanceFromCenter( QVector<QgsTileXYZ> &til
cmp.center = center;
std::sort( tiles.begin(), tiles.end(), cmp );
}

void QgsVectorTileUtils::loadSprites( const QVariantMap &styleDefinition, QgsMapBoxGlStyleConversionContext &context, const QString &styleUrl )
{
if ( styleDefinition.contains( QStringLiteral( "sprite" ) ) && ( context.spriteDefinitions().empty() || context.spriteImage().isNull() ) )
{
// retrieve sprite definition
QString spriteUriBase;
if ( styleDefinition.value( QStringLiteral( "sprite" ) ).toString().startsWith( QLatin1String( "http" ) ) )
{
spriteUriBase = styleDefinition.value( QStringLiteral( "sprite" ) ).toString();
}
else
{
spriteUriBase = styleUrl + '/' + styleDefinition.value( QStringLiteral( "sprite" ) ).toString();
}

for ( int resolution = 2; resolution > 0; resolution-- )
{
QUrl spriteUrl = QUrl( spriteUriBase );
spriteUrl.setPath( spriteUrl.path() + QStringLiteral( "%1.json" ).arg( resolution > 1 ? QStringLiteral( "@%1x" ).arg( resolution ) : QString() ) );
QNetworkRequest request = QNetworkRequest( spriteUrl );
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsVectorTileLayer" ) )
QgsBlockingNetworkRequest networkRequest;
switch ( networkRequest.get( request ) )
{
case QgsBlockingNetworkRequest::NoError:
{
const QgsNetworkReplyContent content = networkRequest.reply();
const QVariantMap spriteDefinition = QgsJsonUtils::parseJson( content.content() ).toMap();

// retrieve sprite images
QUrl spriteUrl = QUrl( spriteUriBase );
spriteUrl.setPath( spriteUrl.path() + QStringLiteral( "%1.png" ).arg( resolution > 1 ? QStringLiteral( "@%1x" ).arg( resolution ) : QString() ) );
QNetworkRequest request = QNetworkRequest( spriteUrl );
QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsVectorTileLayer" ) )
QgsBlockingNetworkRequest networkRequest;
switch ( networkRequest.get( request ) )
{
case QgsBlockingNetworkRequest::NoError:
{
const QgsNetworkReplyContent imageContent = networkRequest.reply();
const QImage spriteImage( QImage::fromData( imageContent.content() ) );
context.setSprites( spriteImage, spriteDefinition );
break;
}

case QgsBlockingNetworkRequest::NetworkError:
case QgsBlockingNetworkRequest::TimeoutError:
case QgsBlockingNetworkRequest::ServerExceptionError:
break;
}

break;
}

case QgsBlockingNetworkRequest::NetworkError:
case QgsBlockingNetworkRequest::TimeoutError:
case QgsBlockingNetworkRequest::ServerExceptionError:
break;
}

if ( !context.spriteDefinitions().isEmpty() )
break;
}
}
}

10 changes: 10 additions & 0 deletions src/core/vectortile/qgsvectortileutils.h
Expand Up @@ -21,6 +21,7 @@
#define SIP_NO_FILE

#include <QSet>
#include <QVariantMap>

class QPointF;
class QPolygon;
Expand All @@ -35,6 +36,7 @@ class QgsTileMatrix;
class QgsTileRange;
class QgsTileXYZ;
class QgsVectorTileLayer;
class QgsMapBoxGlStyleConversionContext;

/**
* \ingroup core
Expand Down Expand Up @@ -84,6 +86,14 @@ class CORE_EXPORT QgsVectorTileUtils
static QString formatXYZUrlTemplate( const QString &url, QgsTileXYZ tile, const QgsTileMatrix &tileMatrix );
//! Checks whether the URL template string is correct (contains {x}, {y} / {-y}, {z} placeholders)
static bool checkXYZUrlTemplate( const QString &url );

/**
* Downloads the sprite image and sets it to the conversion context
* \param styleDefinition the style definition map
* \param context the style conversion context
* \param optional the style url
*/
static void loadSprites( const QVariantMap &styleDefinition, QgsMapBoxGlStyleConversionContext &context, const QString &styleUrl = QString() );
};

#endif // QGSVECTORTILEUTILS_H
6 changes: 6 additions & 0 deletions src/gui/vectortile/qgsvectortilelayerproperties.cpp
Expand Up @@ -23,9 +23,11 @@
#include "qgsvectortilebasicrendererwidget.h"
#include "qgsvectortilebasiclabelingwidget.h"
#include "qgsvectortilelayer.h"
#include "qgsvectortileutils.h"
#include "qgsgui.h"
#include "qgsnative.h"
#include "qgsapplication.h"
#include "qgsjsonutils.h"
#include "qgsmetadatawidget.h"
#include "qgsmaplayerloadstyledialog.h"
#include "qgsmapboxglstyleconverter.h"
Expand Down Expand Up @@ -324,6 +326,10 @@ void QgsVectorTileLayerProperties::loadStyle()
//assume source uses 96 dpi
context.setPixelSizeConversionFactor( 25.4 / 96.0 );

//load sprites
QVariantMap styleDefinition = QgsJsonUtils::parseJson( content ).toMap();
QgsVectorTileUtils::loadSprites( styleDefinition, context );

QgsMapBoxGlStyleConverter converter;

if ( converter.convert( content, &context ) != QgsMapBoxGlStyleConverter::Success )
Expand Down

0 comments on commit a336a23

Please sign in to comment.