diff --git a/python/core/auto_generated/symbology/qgsgeometrygeneratorsymbollayer.sip.in b/python/core/auto_generated/symbology/qgsgeometrygeneratorsymbollayer.sip.in index c187910e8a17..b57fd4ec9f78 100644 --- a/python/core/auto_generated/symbology/qgsgeometrygeneratorsymbollayer.sip.in +++ b/python/core/auto_generated/symbology/qgsgeometrygeneratorsymbollayer.sip.in @@ -40,9 +40,12 @@ that is created by this generator. virtual void startRender( QgsSymbolRenderContext &context ); - virtual void stopRender( QgsSymbolRenderContext &context ); + virtual void startFeatureRender( const QgsFeature &feature, QgsRenderContext &context ); + + virtual void stopFeatureRender( const QgsFeature &feature, QgsRenderContext &context ); + virtual QgsSymbolLayer *clone() const /Factory/; diff --git a/src/core/symbology/qgsgeometrygeneratorsymbollayer.cpp b/src/core/symbology/qgsgeometrygeneratorsymbollayer.cpp index 4e282861b6b7..71b9f3c5144d 100644 --- a/src/core/symbology/qgsgeometrygeneratorsymbollayer.cpp +++ b/src/core/symbology/qgsgeometrygeneratorsymbollayer.cpp @@ -96,6 +96,17 @@ void QgsGeometryGeneratorSymbolLayer::stopRender( QgsSymbolRenderContext &contex mSymbol->stopRender( context.renderContext() ); } +void QgsGeometryGeneratorSymbolLayer::startFeatureRender( const QgsFeature &, QgsRenderContext & ) +{ + mRenderingFeature = true; + mHasRenderedFeature = false; +} + +void QgsGeometryGeneratorSymbolLayer::stopFeatureRender( const QgsFeature &, QgsRenderContext & ) +{ + mRenderingFeature = false; +} + QgsSymbolLayer *QgsGeometryGeneratorSymbolLayer::clone() const { QgsGeometryGeneratorSymbolLayer *clone = new QgsGeometryGeneratorSymbolLayer( mExpression->expression() ); @@ -192,6 +203,9 @@ bool QgsGeometryGeneratorSymbolLayer::isCompatibleWithSymbol( QgsSymbol *symbol } void QgsGeometryGeneratorSymbolLayer::render( QgsSymbolRenderContext &context ) { + if ( mRenderingFeature && mHasRenderedFeature ) + return; + if ( context.feature() ) { QgsExpressionContext &expressionContext = context.renderContext().expressionContext(); @@ -205,6 +219,9 @@ void QgsGeometryGeneratorSymbolLayer::render( QgsSymbolRenderContext &context ) subSymbolExpressionContextScope->setFeature( f ); mSymbol->renderFeature( f, context.renderContext(), -1, context.selected() ); + + if ( mRenderingFeature ) + mHasRenderedFeature = true; } } diff --git a/src/core/symbology/qgsgeometrygeneratorsymbollayer.h b/src/core/symbology/qgsgeometrygeneratorsymbollayer.h index c8cb9a33060c..7832aa20f21c 100644 --- a/src/core/symbology/qgsgeometrygeneratorsymbollayer.h +++ b/src/core/symbology/qgsgeometrygeneratorsymbollayer.h @@ -49,8 +49,9 @@ class CORE_EXPORT QgsGeometryGeneratorSymbolLayer : public QgsSymbolLayer QgsSymbol::SymbolType symbolType() const { return mSymbolType; } void startRender( QgsSymbolRenderContext &context ) override; - void stopRender( QgsSymbolRenderContext &context ) override; + void startFeatureRender( const QgsFeature &feature, QgsRenderContext &context ) override; + void stopFeatureRender( const QgsFeature &feature, QgsRenderContext &context ) override; QgsSymbolLayer *clone() const override SIP_FACTORY; @@ -113,6 +114,9 @@ class CORE_EXPORT QgsGeometryGeneratorSymbolLayer : public QgsSymbolLayer * The type of the sub symbol. */ QgsSymbol::SymbolType mSymbolType; + + bool mRenderingFeature = false; + bool mHasRenderedFeature = false; }; #endif // QGSGEOMETRYGENERATORSYMBOLLAYER_H diff --git a/tests/src/python/test_qgsgeometrygeneratorsymbollayer.py b/tests/src/python/test_qgsgeometrygeneratorsymbollayer.py index d8f8179c917a..016409ecb15c 100644 --- a/tests/src/python/test_qgsgeometrygeneratorsymbollayer.py +++ b/tests/src/python/test_qgsgeometrygeneratorsymbollayer.py @@ -37,7 +37,8 @@ QgsRectangle, QgsGeometryGeneratorSymbolLayer, QgsSymbol, - QgsMultiRenderChecker + QgsMultiRenderChecker, + QgsMapSettings ) from qgis.testing import start_app, unittest @@ -163,6 +164,31 @@ def test_buffer_points(self): self.report += renderchecker.report() self.assertTrue(res) + def test_multi_poly_opacity(self): + # test that multi-type features are only rendered once + + multipoly = QgsVectorLayer(os.path.join(TEST_DATA_DIR, 'multipatch.shp'), 'Polygons', 'ogr') + + sym = QgsFillSymbol.createSimple({'color': '#77fdbf6f', 'outline_color': 'black'}) + + buffer_layer = QgsGeometryGeneratorSymbolLayer.create({'geometryModifier': 'buffer($geometry, -0.01)', 'outline_color': 'black'}) + buffer_layer.setSymbolType(QgsSymbol.Fill) + buffer_layer.setSubSymbol(sym) + geom_symbol = QgsFillSymbol() + geom_symbol.changeSymbolLayer(0, buffer_layer) + multipoly.renderer().setSymbol(geom_symbol) + + mapsettings = QgsMapSettings(self.mapsettings) + mapsettings.setExtent(multipoly.extent()) + mapsettings.setLayers([multipoly]) + + renderchecker = QgsMultiRenderChecker() + renderchecker.setMapSettings(mapsettings) + renderchecker.setControlName('expected_geometrygenerator_opacity') + res = renderchecker.runTest('geometrygenerator_opacity') + self.report += renderchecker.report() + self.assertTrue(res) + if __name__ == '__main__': unittest.main() diff --git a/tests/testdata/control_images/expected_geometrygenerator_marker/expected_geometrygenerator_marker_mask.png b/tests/testdata/control_images/expected_geometrygenerator_marker/expected_geometrygenerator_marker_mask.png index e36f2cba311c..f008f47faaac 100644 Binary files a/tests/testdata/control_images/expected_geometrygenerator_marker/expected_geometrygenerator_marker_mask.png and b/tests/testdata/control_images/expected_geometrygenerator_marker/expected_geometrygenerator_marker_mask.png differ diff --git a/tests/testdata/control_images/expected_geometrygenerator_mixed/expected_geometrygenerator_mixed_mask.png b/tests/testdata/control_images/expected_geometrygenerator_mixed/expected_geometrygenerator_mixed_mask.png index 9d3fa50adfa2..8d8872b30309 100644 Binary files a/tests/testdata/control_images/expected_geometrygenerator_mixed/expected_geometrygenerator_mixed_mask.png and b/tests/testdata/control_images/expected_geometrygenerator_mixed/expected_geometrygenerator_mixed_mask.png differ diff --git a/tests/testdata/control_images/expected_geometrygenerator_opacity/expected_geometrygenerator_opacity.png b/tests/testdata/control_images/expected_geometrygenerator_opacity/expected_geometrygenerator_opacity.png new file mode 100644 index 000000000000..947d2ab4f14c Binary files /dev/null and b/tests/testdata/control_images/expected_geometrygenerator_opacity/expected_geometrygenerator_opacity.png differ