@@ -643,6 +643,27 @@ bool QgsSymbol::hasDataDefinedProperties() const
643643 return false ;
644644}
645645
646+ // /@cond PRIVATE
647+
648+ /* *
649+ * RAII class to pop scope from an expression context on destruction
650+ */
651+ class ExpressionContextScopePopper
652+ {
653+ public:
654+
655+ ExpressionContextScopePopper () = default ;
656+
657+ ~ExpressionContextScopePopper ()
658+ {
659+ if ( context )
660+ context->popScope ();
661+ }
662+
663+ QgsExpressionContext *context = nullptr ;
664+ };
665+ // /@endcond PRIVATE
666+
646667void QgsSymbol::renderFeature ( const QgsFeature &feature, QgsRenderContext &context, int layer, bool selected, bool drawVertexMarker, int currentVertexMarkerType, int currentVertexMarkerSize )
647668{
648669 QgsGeometry geom = feature.geometry ();
@@ -672,9 +693,17 @@ void QgsSymbol::renderFeature( const QgsFeature &feature, QgsRenderContext &cont
672693 mSymbolRenderContext ->setGeometryPartCount ( segmentizedGeometry.geometry ()->partCount () );
673694 mSymbolRenderContext ->setGeometryPartNum ( 1 );
674695
696+ ExpressionContextScopePopper scopePopper;
675697 if ( mSymbolRenderContext ->expressionContextScope () )
676698 {
699+ // this is somewhat nasty - by appending this scope here it's now owned
700+ // by both mSymbolRenderContext AND context.expressionContext()
701+ // the RAII scopePopper is required to make sure it always has ownership transferred back
702+ // from context.expressionContext(), even if exceptions of other early exits occur in this
703+ // function
677704 context.expressionContext ().appendScope ( mSymbolRenderContext ->expressionContextScope () );
705+ scopePopper.context = &context.expressionContext ();
706+
678707 QgsExpressionContextUtils::updateSymbolScope ( this , mSymbolRenderContext ->expressionContextScope () );
679708 mSymbolRenderContext ->expressionContextScope ()->addVariable ( QgsExpressionContextScope::StaticVariable ( QgsExpressionContext::EXPR_GEOMETRY_PART_COUNT, mSymbolRenderContext ->geometryPartCount (), true ) );
680709 mSymbolRenderContext ->expressionContextScope ()->addVariable ( QgsExpressionContextScope::StaticVariable ( QgsExpressionContext::EXPR_GEOMETRY_PART_NUM, 1 , true ) );
@@ -952,9 +981,6 @@ void QgsSymbol::renderFeature( const QgsFeature &feature, QgsRenderContext &cont
952981 }
953982 }
954983 }
955-
956- if ( mSymbolRenderContext ->expressionContextScope () )
957- context.expressionContext ().popScope ();
958984}
959985
960986QgsSymbolRenderContext *QgsSymbol::symbolRenderContext ()
0 commit comments