From 6061030f96fe74163609ff26ef9a583e00590896 Mon Sep 17 00:00:00 2001 From: Denis Rouzaud Date: Fri, 8 Jan 2021 12:02:31 +0100 Subject: [PATCH] enable dynamic SVGs for fill symbol (#40902) --- .../symbology/qgsfillsymbollayer.sip.in | 14 +++++++ src/core/symbology/qgsfillsymbollayer.cpp | 40 +++++++++++++++++-- src/core/symbology/qgsfillsymbollayer.h | 16 +++++++- src/gui/symbology/qgssymbollayerwidget.cpp | 3 +- 4 files changed, 67 insertions(+), 6 deletions(-) diff --git a/python/core/auto_generated/symbology/qgsfillsymbollayer.sip.in b/python/core/auto_generated/symbology/qgsfillsymbollayer.sip.in index 4d3ce6637520..20ee31474f42 100644 --- a/python/core/auto_generated/symbology/qgsfillsymbollayer.sip.in +++ b/python/core/auto_generated/symbology/qgsfillsymbollayer.sip.in @@ -1414,6 +1414,20 @@ Returns the map unit scale for the pattern's stroke. virtual QgsMapUnitScale mapUnitScale() const; + QMap parameters() const; +%Docstring +Returns the dynamic SVG parameters + +.. versionadded:: 3.18 +%End + + void setParameters( const QMap ¶meters ); +%Docstring +Sets the dynamic SVG parameters + +.. versionadded:: 3.18 +%End + protected: virtual void applyDataDefinedSettings( QgsSymbolRenderContext &context ); diff --git a/src/core/symbology/qgsfillsymbollayer.cpp b/src/core/symbology/qgsfillsymbollayer.cpp index 00b0757f3c7a..85f10f877196 100644 --- a/src/core/symbology/qgsfillsymbollayer.cpp +++ b/src/core/symbology/qgsfillsymbollayer.cpp @@ -2005,6 +2005,21 @@ QgsSymbolLayer *QgsSVGFillSymbolLayer::create( const QVariantMap &properties ) symbolLayer->setStrokeWidthMapUnitScale( QgsSymbolLayerUtils::decodeMapUnitScale( properties[QStringLiteral( "outline_width_map_unit_scale" )].toString() ) ); } + if ( properties.contains( QStringLiteral( "parameters" ) ) ) + { + const QVariantMap parameters = properties[QStringLiteral( "parameters" )].toMap(); + QMap parametersProperties; + QVariantMap::const_iterator it = parameters.constBegin(); + for ( ; it != parameters.constEnd(); ++it ) + { + QgsProperty property; + if ( property.loadVariant( it.value() ) ) + parametersProperties.insert( it.key(), property ); + } + + symbolLayer->setParameters( parametersProperties ); + } + symbolLayer->restoreOldDataDefinedProperties( properties ); return symbolLayer.release(); @@ -2030,7 +2045,7 @@ QString QgsSVGFillSymbolLayer::layerType() const void QgsSVGFillSymbolLayer::applyPattern( QBrush &brush, const QString &svgFilePath, double patternWidth, QgsUnitTypes::RenderUnit patternWidthUnit, const QColor &svgFillColor, const QColor &svgStrokeColor, double svgStrokeWidth, QgsUnitTypes::RenderUnit svgStrokeWidthUnit, const QgsSymbolRenderContext &context, - const QgsMapUnitScale &patternWidthMapUnitScale, const QgsMapUnitScale &svgStrokeWidthMapUnitScale ) + const QgsMapUnitScale &patternWidthMapUnitScale, const QgsMapUnitScale &svgStrokeWidthMapUnitScale, const QgsStringMap svgParameters ) { if ( mSvgViewBox.isNull() ) { @@ -2048,7 +2063,7 @@ void QgsSVGFillSymbolLayer::applyPattern( QBrush &brush, const QString &svgFileP bool fitsInCache = true; double strokeWidth = context.renderContext().convertToPainterUnits( svgStrokeWidth, svgStrokeWidthUnit, svgStrokeWidthMapUnitScale ); QImage patternImage = QgsApplication::svgCache()->svgAsImage( svgFilePath, size, svgFillColor, svgStrokeColor, strokeWidth, - context.renderContext().scaleFactor(), fitsInCache, 0, ( context.renderContext().flags() & QgsRenderContext::RenderBlocking ) ); + context.renderContext().scaleFactor(), fitsInCache, 0, ( context.renderContext().flags() & QgsRenderContext::RenderBlocking ), svgParameters ); if ( !fitsInCache ) { QPicture patternPict = QgsApplication::svgCache()->svgAsPicture( svgFilePath, size, svgFillColor, svgStrokeColor, strokeWidth, @@ -2082,8 +2097,9 @@ void QgsSVGFillSymbolLayer::applyPattern( QBrush &brush, const QString &svgFileP void QgsSVGFillSymbolLayer::startRender( QgsSymbolRenderContext &context ) { + QgsStringMap evaluatedParameters = QgsSymbolLayerUtils::evaluatePropertiesMap( mParameters, context.renderContext().expressionContext() ); - applyPattern( mBrush, mSvgFilePath, mPatternWidth, mPatternWidthUnit, mColor, mSvgStrokeColor, mSvgStrokeWidth, mSvgStrokeWidthUnit, context, mPatternWidthMapUnitScale, mSvgStrokeWidthMapUnitScale ); + applyPattern( mBrush, mSvgFilePath, mPatternWidth, mPatternWidthUnit, mColor, mSvgStrokeColor, mSvgStrokeWidth, mSvgStrokeWidthUnit, context, mPatternWidthMapUnitScale, mSvgStrokeWidthMapUnitScale, evaluatedParameters ); if ( mStroke ) { @@ -2126,6 +2142,13 @@ QVariantMap QgsSVGFillSymbolLayer::properties() const map.insert( QStringLiteral( "svg_outline_width_map_unit_scale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mSvgStrokeWidthMapUnitScale ) ); map.insert( QStringLiteral( "outline_width_unit" ), QgsUnitTypes::encodeUnit( mStrokeWidthUnit ) ); map.insert( QStringLiteral( "outline_width_map_unit_scale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mStrokeWidthMapUnitScale ) ); + + QVariantMap parameters; + QMap::const_iterator it = mParameters.constBegin(); + for ( ; it != mParameters.constEnd(); ++it ) + parameters.insert( it.key(), it.value().toVariant() ); + map[QStringLiteral( "parameters" )] = parameters; + return map; } @@ -2151,6 +2174,8 @@ QgsSVGFillSymbolLayer *QgsSVGFillSymbolLayer::clone() const clonedLayer->setStrokeWidthUnit( mStrokeWidthUnit ); clonedLayer->setStrokeWidthMapUnitScale( mStrokeWidthMapUnitScale ); + clonedLayer->setParameters( mParameters ); + if ( mStroke ) { clonedLayer->setSubSymbol( mStroke->clone() ); @@ -2330,8 +2355,10 @@ void QgsSVGFillSymbolLayer::applyDataDefinedSettings( QgsSymbolRenderContext &co context.setOriginalValueVariable( mSvgStrokeWidth ); strokeWidth = mDataDefinedProperties.valueAsDouble( QgsSymbolLayer::PropertyStrokeWidth, context.renderContext().expressionContext(), mSvgStrokeWidth ); } + QgsStringMap evaluatedParameters = QgsSymbolLayerUtils::evaluatePropertiesMap( mParameters, context.renderContext().expressionContext() ); + applyPattern( mBrush, svgFile, width, mPatternWidthUnit, svgFillColor, svgStrokeColor, strokeWidth, - mSvgStrokeWidthUnit, context, mPatternWidthMapUnitScale, mSvgStrokeWidthMapUnitScale ); + mSvgStrokeWidthUnit, context, mPatternWidthMapUnitScale, mSvgStrokeWidthMapUnitScale, evaluatedParameters ); } @@ -2394,6 +2421,11 @@ void QgsSVGFillSymbolLayer::setDefaultSvgParams() } } +void QgsSVGFillSymbolLayer::setParameters( const QMap ¶meters ) +{ + mParameters = parameters; +} + QgsLinePatternFillSymbolLayer::QgsLinePatternFillSymbolLayer() : QgsImageFillSymbolLayer() diff --git a/src/core/symbology/qgsfillsymbollayer.h b/src/core/symbology/qgsfillsymbollayer.h index afeca59ecd3b..64fbc01b87f7 100644 --- a/src/core/symbology/qgsfillsymbollayer.h +++ b/src/core/symbology/qgsfillsymbollayer.h @@ -1254,6 +1254,18 @@ class CORE_EXPORT QgsSVGFillSymbolLayer: public QgsImageFillSymbolLayer void setMapUnitScale( const QgsMapUnitScale &scale ) override; QgsMapUnitScale mapUnitScale() const override; + /** + * Returns the dynamic SVG parameters + * \since QGIS 3.18 + */ + QMap parameters() const { return mParameters; } + + /** + * Sets the dynamic SVG parameters + * \since QGIS 3.18 + */ + void setParameters( const QMap ¶meters ); + protected: void applyDataDefinedSettings( QgsSymbolRenderContext &context ) override; @@ -1264,6 +1276,7 @@ class CORE_EXPORT QgsSVGFillSymbolLayer: public QgsImageFillSymbolLayer double mPatternWidth = 20; QgsUnitTypes::RenderUnit mPatternWidthUnit = QgsUnitTypes::RenderMillimeters; QgsMapUnitScale mPatternWidthMapUnitScale; + QMap mParameters; //! SVG data QByteArray mSvgData; @@ -1285,7 +1298,8 @@ class CORE_EXPORT QgsSVGFillSymbolLayer: public QgsImageFillSymbolLayer //! Applies the svg pattern to the brush void applyPattern( QBrush &brush, const QString &svgFilePath, double patternWidth, QgsUnitTypes::RenderUnit patternWidthUnit, const QColor &svgFillColor, const QColor &svgStrokeColor, - double svgStrokeWidth, QgsUnitTypes::RenderUnit svgStrokeWidthUnit, const QgsSymbolRenderContext &context, const QgsMapUnitScale &patternWidthMapUnitScale, const QgsMapUnitScale &svgStrokeWidthMapUnitScale ); + double svgStrokeWidth, QgsUnitTypes::RenderUnit svgStrokeWidthUnit, const QgsSymbolRenderContext &context, const QgsMapUnitScale &patternWidthMapUnitScale, const QgsMapUnitScale &svgStrokeWidthMapUnitScale, + const QgsStringMap svgParameters ); }; /** diff --git a/src/gui/symbology/qgssymbollayerwidget.cpp b/src/gui/symbology/qgssymbollayerwidget.cpp index 414fcebbfcbd..134f47d21e26 100644 --- a/src/gui/symbology/qgssymbollayerwidget.cpp +++ b/src/gui/symbology/qgssymbollayerwidget.cpp @@ -2729,6 +2729,7 @@ QgsSVGFillSymbolLayerWidget::QgsSVGFillSymbolLayerWidget( QgsVectorLayer *vl, QW mLayer = nullptr; setupUi( this ); + mSvgSelectorWidget->setAllowParameters( true ); mSvgSelectorWidget->sourceLineEdit()->setPropertyOverrideToolButtonVisible( true ); connect( mTextureWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsSVGFillSymbolLayerWidget::mTextureWidthSpinBox_valueChanged ); @@ -2853,7 +2854,7 @@ void QgsSVGFillSymbolLayerWidget::setFile( const QString &name ) void QgsSVGFillSymbolLayerWidget::setSvgParameters( const QMap ¶meters ) { - // TODO mLayer->setParameters(parameters); + mLayer->setParameters( parameters ); whileBlocking( mSvgSelectorWidget )->setSvgParameters( parameters ); updateParamGui();