Skip to content

Commit

Permalink
Convert styles where interpolated colors are expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
mhugent committed Sep 3, 2021
1 parent cf3de15 commit 78f6376
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 28 deletions.
Expand Up @@ -457,6 +457,15 @@ Interpolates a list which starts with the interpolate function.
This is private API only, and may change in future QGIS versions
%End

static QString parseColorExpression( const QVariant &colorExpression, QgsMapBoxGlStyleConversionContext &context );
%Docstring
Converts an expression representing a color to a string (can be color string or an expression where a color is expected)

:param colorExpression: the color expression
:param context: the style conversion context
@return the QGIS expression string
%End

static QColor parseColor( const QVariant &color, QgsMapBoxGlStyleConversionContext &context );
%Docstring
Parses a ``color`` in one of these supported formats:
Expand Down
60 changes: 32 additions & 28 deletions src/core/vectortile/qgsmapboxglstyleconverter.cpp
Expand Up @@ -2003,6 +2003,7 @@ QgsProperty QgsMapBoxGlStyleConverter::parseInterpolateColorByZoom( const QVaria
return QgsProperty();

QString caseString = QStringLiteral( "CASE " );
QString colorComponent( "color_part(%1,'%2')" );

for ( int i = 0; i < stops.length() - 1; ++i )
{
Expand All @@ -2011,40 +2012,27 @@ QgsProperty QgsMapBoxGlStyleConverter::parseInterpolateColorByZoom( const QVaria
// step top zoom
const QString tz = stops.at( i + 1 ).toList().value( 0 ).toString();

const QColor bottomColor = parseColor( stops.at( i ).toList().value( 1 ), context );
const QColor topColor = parseColor( stops.at( i + 1 ).toList().value( 1 ), context );

int bcHue;
int bcSat;
int bcLight;
int bcAlpha;
colorAsHslaComponents( bottomColor, bcHue, bcSat, bcLight, bcAlpha );
int tcHue;
int tcSat;
int tcLight;
int tcAlpha;
colorAsHslaComponents( topColor, tcHue, tcSat, tcLight, tcAlpha );
const QVariant bcVariant = stops.at( i ).toList().value( 1 );
const QVariant tcVariant = stops.at( i + 1 ).toList().value( 1 );
QString bottomColor = parseColorExpression( bcVariant, context );
QString topColor = parseColorExpression( tcVariant, context );

caseString += QStringLiteral( "WHEN @vector_tile_zoom >= %1 AND @vector_tile_zoom < %2 THEN color_hsla("
"%3, %4, %5, %6) " ).arg( bz, tz,
interpolateExpression( bz.toDouble(), tz.toDouble(), bcHue, tcHue, base, context ),
interpolateExpression( bz.toDouble(), tz.toDouble(), bcSat, tcSat, base, context ),
interpolateExpression( bz.toDouble(), tz.toDouble(), bcLight, tcLight, base, context ),
interpolateExpression( bz.toDouble(), tz.toDouble(), bcAlpha, tcAlpha, base, context ) );
interpolateExpression( bz.toDouble(), tz.toDouble(), colorComponent.arg( bottomColor ).arg( "hsl_hue" ), colorComponent.arg( topColor ).arg( "hsl_hue" ), base, context ),
interpolateExpression( bz.toDouble(), tz.toDouble(), colorComponent.arg( bottomColor ).arg( "hsl_saturation" ), colorComponent.arg( topColor ).arg( "hsl_saturation" ), base, context ),
interpolateExpression( bz.toDouble(), tz.toDouble(), colorComponent.arg( bottomColor ).arg( "lightness" ), colorComponent.arg( topColor ).arg( "lightness" ), base, context ),
interpolateExpression( bz.toDouble(), tz.toDouble(), colorComponent.arg( bottomColor ).arg( "alpha" ), colorComponent.arg( topColor ).arg( "alpha" ), base, context ) );
}

// top color
const QString tz = stops.last().toList().value( 0 ).toString();
const QColor topColor = parseColor( stops.last().toList().value( 1 ), context );
int tcHue;
int tcSat;
int tcLight;
int tcAlpha;
colorAsHslaComponents( topColor, tcHue, tcSat, tcLight, tcAlpha );
const QVariant tcVariant = stops.last().toList().value( 1 );
QString topColor = parseColorExpression( tcVariant, context );

caseString += QStringLiteral( "WHEN @vector_tile_zoom >= %1 THEN color_hsla(%2, %3, %4, %5) "
"ELSE color_hsla(%2, %3, %4, %5) END" ).arg( tz )
.arg( tcHue ).arg( tcSat ).arg( tcLight ).arg( tcAlpha );
.arg( colorComponent.arg( topColor ).arg( "hsl_hue" ) ).arg( colorComponent.arg( topColor ).arg( "hsl_saturation" ) ).arg( colorComponent.arg( topColor ).arg( "lightness" ) ).arg( colorComponent.arg( topColor ).arg( "alpha" ) );


if ( !stops.empty() && defaultColor )
Expand Down Expand Up @@ -2458,6 +2446,15 @@ QgsProperty QgsMapBoxGlStyleConverter::parseInterpolateListByZoom( const QVarian
return QgsProperty();
}

QString QgsMapBoxGlStyleConverter::parseColorExpression( const QVariant &colorExpression, QgsMapBoxGlStyleConversionContext &context )
{
if ( ( QMetaType::Type )colorExpression.type() == QMetaType::QVariantList )
{
return parseExpression( colorExpression.toList(), context );
}
return parseValue( colorExpression, context );
}

QColor QgsMapBoxGlStyleConverter::parseColor( const QVariant &color, QgsMapBoxGlStyleConversionContext &context )
{
if ( color.type() != QVariant::String )
Expand Down Expand Up @@ -2646,7 +2643,7 @@ QString QgsMapBoxGlStyleConverter::parseExpression( const QVariantList &expressi
QStringList parts;
for ( const QVariant &p : expression.at( 2 ).toList() )
{
parts << QgsExpression::quotedValue( p );
parts << parseValue( p, context );
}

if ( parts.size() > 1 )
Expand Down Expand Up @@ -2689,9 +2686,9 @@ QString QgsMapBoxGlStyleConverter::parseExpression( const QVariantList &expressi
caseString += QStringLiteral( "WHEN (%1) " ).arg( QgsExpression::createFieldEqualityExpression( attribute, expression.at( i ) ) );
}

caseString += QStringLiteral( "THEN %1 " ).arg( QgsExpression::quotedValue( expression.at( i + 1 ) ) );
caseString += QStringLiteral( "THEN %1 " ).arg( parseValue( expression.at( i + 1 ), context ) );
}
caseString += QStringLiteral( "ELSE %1 END" ).arg( QgsExpression::quotedValue( expression.last() ) );
caseString += QStringLiteral( "ELSE %1 END" ).arg( parseValue( expression.last(), context ) );
return caseString;
}
}
Expand Down Expand Up @@ -2924,14 +2921,21 @@ QString QgsMapBoxGlStyleConverter::retrieveSpriteAsBase64( const QVariant &value

QString QgsMapBoxGlStyleConverter::parseValue( const QVariant &value, QgsMapBoxGlStyleConversionContext &context )
{
QColor c;
QString debug;
switch ( value.type() )
{
case QVariant::List:
case QVariant::StringList:
return parseExpression( value.toList(), context );

case QVariant::String:
return QgsExpression::quotedValue( value.toString() );
c = parseColor( value, context );
if ( !c.isValid() )
{
return QgsExpression::quotedValue( value.toString() );
}
return QString( "color_rgba(%1,%2,%3,%4)" ).arg( c.red() ).arg( c.green() ).arg( c.blue() ).arg( c.alpha() );

case QVariant::Int:
case QVariant::Double:
Expand Down
8 changes: 8 additions & 0 deletions src/core/vectortile/qgsmapboxglstyleconverter.h
Expand Up @@ -450,6 +450,14 @@ class CORE_EXPORT QgsMapBoxGlStyleConverter
static QgsProperty parseInterpolateListByZoom( const QVariantList &json, PropertyType type, QgsMapBoxGlStyleConversionContext &context, double multiplier = 1,
int maxOpacity = 255, QColor *defaultColor SIP_OUT = nullptr, double *defaultNumber SIP_OUT = nullptr );

/**
* Converts an expression representing a color to a string (can be color string or an expression where a color is expected)
* \param colorExpression the color expression
* \param context the style conversion context
* @return the QGIS expression string
*/
static QString parseColorExpression( const QVariant &colorExpression, QgsMapBoxGlStyleConversionContext &context );

/**
* Parses a \a color in one of these supported formats:
*
Expand Down

0 comments on commit 78f6376

Please sign in to comment.