mirror of
https://github.com/qgis/QGIS.git
synced 2025-11-22 00:14:55 -05:00
[vector tiles] Fix sprites not loaded from the OSM shortbread styles
This commit is contained in:
parent
b7de3815a4
commit
09c5478ad2
@ -90,39 +90,54 @@ sizes when converting styles.
|
||||
.. seealso:: :py:func:`pixelSizeConversionFactor`
|
||||
%End
|
||||
|
||||
QImage spriteImage() const;
|
||||
QStringList spriteCategories() const;
|
||||
%Docstring
|
||||
Returns the sprite image to use during conversion, or an invalid image
|
||||
if this is not set.
|
||||
Returns the list of sprite categories to use during conversion, or an
|
||||
empty list of none is set.
|
||||
|
||||
.. seealso:: :py:func:`spriteDefinitions`
|
||||
|
||||
.. seealso:: :py:func:`spriteImage`
|
||||
|
||||
.. versionadded:: 3.44
|
||||
%End
|
||||
|
||||
QImage spriteImage( const QString &category = QString() ) const;
|
||||
%Docstring
|
||||
Returns the sprite image for a given ``category`` to use during
|
||||
conversion, or an invalid image if this is not set.
|
||||
|
||||
.. seealso:: :py:func:`spriteCategories`
|
||||
|
||||
.. seealso:: :py:func:`spriteDefinitions`
|
||||
|
||||
.. seealso:: :py:func:`setSprites`
|
||||
%End
|
||||
|
||||
QVariantMap spriteDefinitions() const;
|
||||
QVariantMap spriteDefinitions( const QString &category = QString() ) const;
|
||||
%Docstring
|
||||
Returns the sprite definitions to use during conversion.
|
||||
Returns the sprite definitions for a given ``category`` to use during
|
||||
conversion.
|
||||
|
||||
.. seealso:: :py:func:`spriteImage`
|
||||
|
||||
.. seealso:: :py:func:`setSprites`
|
||||
%End
|
||||
|
||||
void setSprites( const QImage &image, const QVariantMap &definitions );
|
||||
void setSprites( const QImage &image, const QVariantMap &definitions, const QString &category = QString() );
|
||||
%Docstring
|
||||
Sets the sprite ``image`` and ``definitions`` JSON to use during
|
||||
conversion.
|
||||
Sets the sprite ``image`` and ``definitions`` JSON for a given
|
||||
``category`` to use during conversion.
|
||||
|
||||
.. seealso:: :py:func:`spriteImage`
|
||||
|
||||
.. seealso:: :py:func:`spriteDefinitions`
|
||||
%End
|
||||
|
||||
void setSprites( const QImage &image, const QString &definitions );
|
||||
void setSprites( const QImage &image, const QString &definitions, const QString &category = QString() );
|
||||
%Docstring
|
||||
Sets the sprite ``image`` and ``definitions`` JSON string to use during
|
||||
conversion.
|
||||
Sets the sprite ``image`` and ``definitions`` JSON string for a given
|
||||
``category`` to use during conversion.
|
||||
|
||||
.. seealso:: :py:func:`spriteImage`
|
||||
|
||||
|
||||
@ -90,39 +90,54 @@ sizes when converting styles.
|
||||
.. seealso:: :py:func:`pixelSizeConversionFactor`
|
||||
%End
|
||||
|
||||
QImage spriteImage() const;
|
||||
QStringList spriteCategories() const;
|
||||
%Docstring
|
||||
Returns the sprite image to use during conversion, or an invalid image
|
||||
if this is not set.
|
||||
Returns the list of sprite categories to use during conversion, or an
|
||||
empty list of none is set.
|
||||
|
||||
.. seealso:: :py:func:`spriteDefinitions`
|
||||
|
||||
.. seealso:: :py:func:`spriteImage`
|
||||
|
||||
.. versionadded:: 3.44
|
||||
%End
|
||||
|
||||
QImage spriteImage( const QString &category = QString() ) const;
|
||||
%Docstring
|
||||
Returns the sprite image for a given ``category`` to use during
|
||||
conversion, or an invalid image if this is not set.
|
||||
|
||||
.. seealso:: :py:func:`spriteCategories`
|
||||
|
||||
.. seealso:: :py:func:`spriteDefinitions`
|
||||
|
||||
.. seealso:: :py:func:`setSprites`
|
||||
%End
|
||||
|
||||
QVariantMap spriteDefinitions() const;
|
||||
QVariantMap spriteDefinitions( const QString &category = QString() ) const;
|
||||
%Docstring
|
||||
Returns the sprite definitions to use during conversion.
|
||||
Returns the sprite definitions for a given ``category`` to use during
|
||||
conversion.
|
||||
|
||||
.. seealso:: :py:func:`spriteImage`
|
||||
|
||||
.. seealso:: :py:func:`setSprites`
|
||||
%End
|
||||
|
||||
void setSprites( const QImage &image, const QVariantMap &definitions );
|
||||
void setSprites( const QImage &image, const QVariantMap &definitions, const QString &category = QString() );
|
||||
%Docstring
|
||||
Sets the sprite ``image`` and ``definitions`` JSON to use during
|
||||
conversion.
|
||||
Sets the sprite ``image`` and ``definitions`` JSON for a given
|
||||
``category`` to use during conversion.
|
||||
|
||||
.. seealso:: :py:func:`spriteImage`
|
||||
|
||||
.. seealso:: :py:func:`spriteDefinitions`
|
||||
%End
|
||||
|
||||
void setSprites( const QImage &image, const QString &definitions );
|
||||
void setSprites( const QImage &image, const QString &definitions, const QString &category = QString() );
|
||||
%Docstring
|
||||
Sets the sprite ``image`` and ``definitions`` JSON string to use during
|
||||
conversion.
|
||||
Sets the sprite ``image`` and ``definitions`` JSON string for a given
|
||||
``category`` to use during conversion.
|
||||
|
||||
.. seealso:: :py:func:`spriteImage`
|
||||
|
||||
|
||||
@ -3524,23 +3524,46 @@ QString QgsMapBoxGlStyleConverter::parseExpression( const QVariantList &expressi
|
||||
|
||||
QImage QgsMapBoxGlStyleConverter::retrieveSprite( const QString &name, QgsMapBoxGlStyleConversionContext &context, QSize &spriteSize )
|
||||
{
|
||||
if ( context.spriteImage().isNull() )
|
||||
QImage spriteImage;
|
||||
QString category;
|
||||
QString actualName = name;
|
||||
const int categorySeparator = name.indexOf( ':' );
|
||||
if ( categorySeparator > 0 )
|
||||
{
|
||||
category = name.left( categorySeparator );
|
||||
if ( context.spriteCategories().contains( category ) )
|
||||
{
|
||||
actualName = name.mid( categorySeparator + 1 );
|
||||
spriteImage = context.spriteImage( category );
|
||||
}
|
||||
else
|
||||
{
|
||||
category.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if ( category.isEmpty() )
|
||||
{
|
||||
spriteImage = context.spriteImage();
|
||||
}
|
||||
|
||||
if ( spriteImage.isNull() )
|
||||
{
|
||||
context.pushWarning( QObject::tr( "%1: Could not retrieve sprite '%2'" ).arg( context.layerId(), name ) );
|
||||
return QImage();
|
||||
}
|
||||
|
||||
const QVariantMap spriteDefinition = context.spriteDefinitions().value( name ).toMap();
|
||||
const QVariantMap spriteDefinition = context.spriteDefinitions( category ).value( actualName ).toMap();
|
||||
if ( spriteDefinition.size() == 0 )
|
||||
{
|
||||
context.pushWarning( QObject::tr( "%1: Could not retrieve sprite '%2'" ).arg( context.layerId(), name ) );
|
||||
return QImage();
|
||||
}
|
||||
|
||||
const QImage sprite = context.spriteImage().copy( spriteDefinition.value( QStringLiteral( "x" ) ).toInt(),
|
||||
spriteDefinition.value( QStringLiteral( "y" ) ).toInt(),
|
||||
spriteDefinition.value( QStringLiteral( "width" ) ).toInt(),
|
||||
spriteDefinition.value( QStringLiteral( "height" ) ).toInt() );
|
||||
const QImage sprite = spriteImage.copy( spriteDefinition.value( QStringLiteral( "x" ) ).toInt(),
|
||||
spriteDefinition.value( QStringLiteral( "y" ) ).toInt(),
|
||||
spriteDefinition.value( QStringLiteral( "width" ) ).toInt(),
|
||||
spriteDefinition.value( QStringLiteral( "height" ) ).toInt() );
|
||||
if ( sprite.isNull() )
|
||||
{
|
||||
context.pushWarning( QObject::tr( "%1: Could not retrieve sprite '%2'" ).arg( context.layerId(), name ) );
|
||||
@ -4091,25 +4114,30 @@ void QgsMapBoxGlStyleConversionContext::setPixelSizeConversionFactor( double siz
|
||||
mSizeConversionFactor = sizeConversionFactor;
|
||||
}
|
||||
|
||||
QImage QgsMapBoxGlStyleConversionContext::spriteImage() const
|
||||
QStringList QgsMapBoxGlStyleConversionContext::spriteCategories() const
|
||||
{
|
||||
return mSpriteImage;
|
||||
return mSpriteImage.keys();
|
||||
}
|
||||
|
||||
QVariantMap QgsMapBoxGlStyleConversionContext::spriteDefinitions() const
|
||||
QImage QgsMapBoxGlStyleConversionContext::spriteImage( const QString &category ) const
|
||||
{
|
||||
return mSpriteDefinitions;
|
||||
return mSpriteImage.contains( category ) ? mSpriteImage[category] : QImage();
|
||||
}
|
||||
|
||||
void QgsMapBoxGlStyleConversionContext::setSprites( const QImage &image, const QVariantMap &definitions )
|
||||
QVariantMap QgsMapBoxGlStyleConversionContext::spriteDefinitions( const QString &category ) const
|
||||
{
|
||||
mSpriteImage = image;
|
||||
mSpriteDefinitions = definitions;
|
||||
return mSpriteDefinitions.contains( category ) ? mSpriteDefinitions[category] : QVariantMap();
|
||||
}
|
||||
|
||||
void QgsMapBoxGlStyleConversionContext::setSprites( const QImage &image, const QString &definitions )
|
||||
void QgsMapBoxGlStyleConversionContext::setSprites( const QImage &image, const QVariantMap &definitions, const QString &category )
|
||||
{
|
||||
setSprites( image, QgsJsonUtils::parseJson( definitions ).toMap() );
|
||||
mSpriteImage[category] = image;
|
||||
mSpriteDefinitions[category] = definitions;
|
||||
}
|
||||
|
||||
void QgsMapBoxGlStyleConversionContext::setSprites( const QImage &image, const QString &definitions, const QString &category )
|
||||
{
|
||||
setSprites( image, QgsJsonUtils::parseJson( definitions ).toMap(), category );
|
||||
}
|
||||
|
||||
QString QgsMapBoxGlStyleConversionContext::layerId() const
|
||||
|
||||
@ -103,36 +103,46 @@ class CORE_EXPORT QgsMapBoxGlStyleConversionContext
|
||||
void setPixelSizeConversionFactor( double sizeConversionFactor );
|
||||
|
||||
/**
|
||||
* Returns the sprite image to use during conversion, or an invalid image if this is not set.
|
||||
* Returns the list of sprite categories to use during conversion, or an empty list of none is set.
|
||||
*
|
||||
* \see spriteDefinitions()
|
||||
* \see spriteImage()
|
||||
* \since QGIS 3.44
|
||||
*/
|
||||
QStringList spriteCategories() const;
|
||||
|
||||
/**
|
||||
* Returns the sprite image for a given \a category to use during conversion, or an invalid image if this is not set.
|
||||
*
|
||||
* \see spriteCategories()
|
||||
* \see spriteDefinitions()
|
||||
* \see setSprites()
|
||||
*/
|
||||
QImage spriteImage() const;
|
||||
QImage spriteImage( const QString &category = QString() ) const;
|
||||
|
||||
/**
|
||||
* Returns the sprite definitions to use during conversion.
|
||||
* Returns the sprite definitions for a given \a category to use during conversion.
|
||||
*
|
||||
* \see spriteImage()
|
||||
* \see setSprites()
|
||||
*/
|
||||
QVariantMap spriteDefinitions() const;
|
||||
QVariantMap spriteDefinitions( const QString &category = QString() ) const;
|
||||
|
||||
/**
|
||||
* Sets the sprite \a image and \a definitions JSON to use during conversion.
|
||||
* Sets the sprite \a image and \a definitions JSON for a given \a category to use during conversion.
|
||||
*
|
||||
* \see spriteImage()
|
||||
* \see spriteDefinitions()
|
||||
*/
|
||||
void setSprites( const QImage &image, const QVariantMap &definitions );
|
||||
void setSprites( const QImage &image, const QVariantMap &definitions, const QString &category = QString() );
|
||||
|
||||
/**
|
||||
* Sets the sprite \a image and \a definitions JSON string to use during conversion.
|
||||
* Sets the sprite \a image and \a definitions JSON string for a given \a category to use during conversion.
|
||||
*
|
||||
* \see spriteImage()
|
||||
* \see spriteDefinitions()
|
||||
*/
|
||||
void setSprites( const QImage &image, const QString &definitions );
|
||||
void setSprites( const QImage &image, const QString &definitions, const QString &category = QString() );
|
||||
|
||||
/**
|
||||
* Returns the layer ID of the layer currently being converted.
|
||||
@ -158,8 +168,8 @@ class CORE_EXPORT QgsMapBoxGlStyleConversionContext
|
||||
|
||||
double mSizeConversionFactor = 1.0;
|
||||
|
||||
QImage mSpriteImage;
|
||||
QVariantMap mSpriteDefinitions;
|
||||
QMap<QString, QImage> mSpriteImage;
|
||||
QMap<QString, QVariantMap> mSpriteDefinitions;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -320,66 +320,101 @@ void QgsVectorTileUtils::sortTilesByDistanceFromCenter( QVector<QgsTileXYZ> &til
|
||||
|
||||
void QgsVectorTileUtils::loadSprites( const QVariantMap &styleDefinition, QgsMapBoxGlStyleConversionContext &context, const QString &styleUrl )
|
||||
{
|
||||
if ( styleDefinition.contains( QStringLiteral( "sprite" ) ) && ( context.spriteDefinitions().empty() || context.spriteImage().isNull() ) )
|
||||
if ( styleDefinition.contains( QStringLiteral( "sprite" ) ) && ( context.spriteCategories().isEmpty() ) )
|
||||
{
|
||||
// retrieve sprite definition
|
||||
QString spriteUriBase;
|
||||
if ( styleDefinition.value( QStringLiteral( "sprite" ) ).toString().startsWith( QLatin1String( "http" ) ) )
|
||||
auto prepareSpriteUrl = []( const QString & sprite, const QString & styleUrl )
|
||||
{
|
||||
spriteUriBase = styleDefinition.value( QStringLiteral( "sprite" ) ).toString();
|
||||
if ( sprite.startsWith( QLatin1String( "http" ) ) )
|
||||
{
|
||||
return sprite;
|
||||
}
|
||||
else if ( sprite.startsWith( QLatin1String( "/" ) ) )
|
||||
{
|
||||
const QUrl url( styleUrl );
|
||||
return QStringLiteral( "%1://%2%3" ).arg( url.scheme(), url.host(), sprite );
|
||||
}
|
||||
|
||||
return QStringLiteral( "%1/%2" ).arg( styleUrl, sprite );
|
||||
};
|
||||
|
||||
// retrieve sprite definition
|
||||
QMap<QString, QString> sprites;
|
||||
const QVariant spriteVariant = styleDefinition.value( QStringLiteral( "sprite" ) );
|
||||
if ( spriteVariant.userType() == QMetaType::Type::QVariantList )
|
||||
{
|
||||
const QVariantList spriteList = spriteVariant.toList();
|
||||
for ( const QVariant &spriteItem : spriteList )
|
||||
{
|
||||
QVariantMap spriteMap = spriteItem.toMap();
|
||||
if ( spriteMap.contains( QStringLiteral( "id" ) ) && spriteMap.contains( "url" ) )
|
||||
{
|
||||
sprites[spriteMap.value( QStringLiteral( "id" ) ).toString()] = prepareSpriteUrl( spriteMap.value( QStringLiteral( "url" ) ).toString(), styleUrl );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
spriteUriBase = styleUrl + '/' + styleDefinition.value( QStringLiteral( "sprite" ) ).toString();
|
||||
sprites[""] = prepareSpriteUrl( spriteVariant.toString(), styleUrl );
|
||||
}
|
||||
|
||||
for ( int resolution = 2; resolution > 0; resolution-- )
|
||||
if ( sprites.isEmpty() )
|
||||
{
|
||||
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();
|
||||
return;
|
||||
}
|
||||
|
||||
// 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 ) )
|
||||
QMap<QString, QString>::const_iterator spritesIterator = sprites.constBegin();
|
||||
while ( spritesIterator != sprites.end() )
|
||||
{
|
||||
for ( int resolution = 2; resolution > 0; resolution-- )
|
||||
{
|
||||
QUrl spriteUrl = QUrl( spritesIterator.value() );
|
||||
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:
|
||||
{
|
||||
case QgsBlockingNetworkRequest::NoError:
|
||||
const QgsNetworkReplyContent content = networkRequest.reply();
|
||||
const QVariantMap spriteDefinition = QgsJsonUtils::parseJson( content.content() ).toMap();
|
||||
|
||||
// retrieve sprite images
|
||||
QUrl spriteUrl = QUrl( spritesIterator.value() );
|
||||
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 ) )
|
||||
{
|
||||
const QgsNetworkReplyContent imageContent = networkRequest.reply();
|
||||
const QImage spriteImage( QImage::fromData( imageContent.content() ) );
|
||||
context.setSprites( spriteImage, spriteDefinition );
|
||||
break;
|
||||
case QgsBlockingNetworkRequest::NoError:
|
||||
{
|
||||
const QgsNetworkReplyContent imageContent = networkRequest.reply();
|
||||
const QImage spriteImage( QImage::fromData( imageContent.content() ) );
|
||||
context.setSprites( spriteImage, spriteDefinition, spritesIterator.key() );
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsBlockingNetworkRequest::NetworkError:
|
||||
case QgsBlockingNetworkRequest::TimeoutError:
|
||||
case QgsBlockingNetworkRequest::ServerExceptionError:
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsBlockingNetworkRequest::NetworkError:
|
||||
case QgsBlockingNetworkRequest::TimeoutError:
|
||||
case QgsBlockingNetworkRequest::ServerExceptionError:
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case QgsBlockingNetworkRequest::NetworkError:
|
||||
case QgsBlockingNetworkRequest::TimeoutError:
|
||||
case QgsBlockingNetworkRequest::ServerExceptionError:
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsBlockingNetworkRequest::NetworkError:
|
||||
case QgsBlockingNetworkRequest::TimeoutError:
|
||||
case QgsBlockingNetworkRequest::ServerExceptionError:
|
||||
if ( !context.spriteDefinitions().isEmpty() )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !context.spriteDefinitions().isEmpty() )
|
||||
break;
|
||||
++spritesIterator;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2735,6 +2735,55 @@ class TestQgsMapBoxGlStyleConverter(QgisTestCase):
|
||||
'CASE WHEN "lake_depth" IS NOT NULL THEN 24 WHEN length(to_string("ele")) IS 3 THEN 18 ELSE 24 END',
|
||||
)
|
||||
|
||||
def testRetrieveSpriteWithCategory(self):
|
||||
context = QgsMapBoxGlStyleConversionContext()
|
||||
sprite_image_file = (
|
||||
f"{TEST_DATA_DIR}/vector_tile/sprites/swisstopo-sprite@2x.png"
|
||||
)
|
||||
with open(sprite_image_file, "rb") as f:
|
||||
sprite_image = QImage()
|
||||
sprite_image.loadFromData(f.read())
|
||||
sprite_definition_file = (
|
||||
f"{TEST_DATA_DIR}/vector_tile/sprites/swisstopo-sprite@2x.json"
|
||||
)
|
||||
with open(sprite_definition_file) as f:
|
||||
sprite_definition = json.load(f)
|
||||
context.setSprites(sprite_image, sprite_definition, "basics")
|
||||
self.assertEqual(context.spriteCategories(), ["basics"])
|
||||
|
||||
# swisstopo - lightbasemap - sinkhole
|
||||
icon_image = [
|
||||
"match",
|
||||
["get", "class"],
|
||||
"sinkhole",
|
||||
"basics:arrow_brown",
|
||||
["sinkhole_rock", "sinkhole_scree"],
|
||||
"basics:arrow_grey",
|
||||
["sinkhole_ice", "sinkhole_water"],
|
||||
"basics:arrow_blue",
|
||||
"",
|
||||
]
|
||||
sprite, size, sprite_property, sprite_size_property = (
|
||||
QgsMapBoxGlStyleConverter.retrieveSpriteAsBase64WithProperties(
|
||||
icon_image, context
|
||||
)
|
||||
)
|
||||
|
||||
def strip_base64(s):
|
||||
pos = 0
|
||||
while True:
|
||||
pos = s.find("'base64:", pos)
|
||||
if pos < 0:
|
||||
break
|
||||
end_pos = s.find("'", pos + 1)
|
||||
assert end_pos > pos
|
||||
s = s[0:pos] + "'base64:[snip]'" + s[end_pos + 1 :]
|
||||
pos += len("'base64:")
|
||||
return s
|
||||
|
||||
expected = "CASE WHEN \"class\" IN ('sinkhole') THEN 'base64:[snip]' WHEN \"class\" IN ('sinkhole_rock','sinkhole_scree') THEN 'base64:[snip]' WHEN \"class\" IN ('sinkhole_ice','sinkhole_water') THEN 'base64:[snip]' ELSE '' END"
|
||||
self.assertEqual(strip_base64(sprite_property), expected)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user