Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Set new Qgis::RenderContextFlag::RenderingSubSymbol flag on render co…
…ntexts

whenever a subsymbol component of a parent symbol is being rendered

This flag allows symbol layers to refine their behaviour based on whether
they are a subsymbol or not.
  • Loading branch information
nyalldawson committed Oct 23, 2021
1 parent 757c69e commit 40279cb
Show file tree
Hide file tree
Showing 9 changed files with 52 additions and 1 deletion.
5 changes: 4 additions & 1 deletion python/core/auto_additions/qgis.py
Expand Up @@ -874,7 +874,10 @@
QgsRenderContext.ApplyClipAfterReprojection = Qgis.RenderContextFlag.ApplyClipAfterReprojection
QgsRenderContext.ApplyClipAfterReprojection.is_monkey_patched = True
QgsRenderContext.ApplyClipAfterReprojection.__doc__ = "Feature geometry clipping to mapExtent() must be performed after the geometries are transformed using coordinateTransform(). Usually feature geometry clipping occurs using the extent() in the layer's CRS prior to geometry transformation, but in some cases when extent() could not be accurately calculated it is necessary to clip geometries to mapExtent() AFTER transforming them using coordinateTransform()."
Qgis.RenderContextFlag.__doc__ = 'Flags which affect rendering operations.\n\n.. versionadded:: 3.22\n\n' + '* ``DrawEditingInfo``: ' + Qgis.RenderContextFlag.DrawEditingInfo.__doc__ + '\n' + '* ``ForceVectorOutput``: ' + Qgis.RenderContextFlag.ForceVectorOutput.__doc__ + '\n' + '* ``UseAdvancedEffects``: ' + Qgis.RenderContextFlag.UseAdvancedEffects.__doc__ + '\n' + '* ``UseRenderingOptimization``: ' + Qgis.RenderContextFlag.UseRenderingOptimization.__doc__ + '\n' + '* ``DrawSelection``: ' + Qgis.RenderContextFlag.DrawSelection.__doc__ + '\n' + '* ``DrawSymbolBounds``: ' + Qgis.RenderContextFlag.DrawSymbolBounds.__doc__ + '\n' + '* ``RenderMapTile``: ' + Qgis.RenderContextFlag.RenderMapTile.__doc__ + '\n' + '* ``Antialiasing``: ' + Qgis.RenderContextFlag.Antialiasing.__doc__ + '\n' + '* ``RenderPartialOutput``: ' + Qgis.RenderContextFlag.RenderPartialOutput.__doc__ + '\n' + '* ``RenderPreviewJob``: ' + Qgis.RenderContextFlag.RenderPreviewJob.__doc__ + '\n' + '* ``RenderBlocking``: ' + Qgis.RenderContextFlag.RenderBlocking.__doc__ + '\n' + '* ``RenderSymbolPreview``: ' + Qgis.RenderContextFlag.RenderSymbolPreview.__doc__ + '\n' + '* ``LosslessImageRendering``: ' + Qgis.RenderContextFlag.LosslessImageRendering.__doc__ + '\n' + '* ``ApplyScalingWorkaroundForTextRendering``: ' + Qgis.RenderContextFlag.ApplyScalingWorkaroundForTextRendering.__doc__ + '\n' + '* ``Render3DMap``: ' + Qgis.RenderContextFlag.Render3DMap.__doc__ + '\n' + '* ``ApplyClipAfterReprojection``: ' + Qgis.RenderContextFlag.ApplyClipAfterReprojection.__doc__
QgsRenderContext.RenderingSubSymbol = Qgis.RenderContextFlag.RenderingSubSymbol
QgsRenderContext.RenderingSubSymbol.is_monkey_patched = True
QgsRenderContext.RenderingSubSymbol.__doc__ = "Set whenever a sub-symbol of a parent symbol is currently being rendered. Can be used during symbol and symbol layer rendering to determine whether the symbol being rendered is a subsymbol. (Since QGIS 3.24)"
Qgis.RenderContextFlag.__doc__ = 'Flags which affect rendering operations.\n\n.. versionadded:: 3.22\n\n' + '* ``DrawEditingInfo``: ' + Qgis.RenderContextFlag.DrawEditingInfo.__doc__ + '\n' + '* ``ForceVectorOutput``: ' + Qgis.RenderContextFlag.ForceVectorOutput.__doc__ + '\n' + '* ``UseAdvancedEffects``: ' + Qgis.RenderContextFlag.UseAdvancedEffects.__doc__ + '\n' + '* ``UseRenderingOptimization``: ' + Qgis.RenderContextFlag.UseRenderingOptimization.__doc__ + '\n' + '* ``DrawSelection``: ' + Qgis.RenderContextFlag.DrawSelection.__doc__ + '\n' + '* ``DrawSymbolBounds``: ' + Qgis.RenderContextFlag.DrawSymbolBounds.__doc__ + '\n' + '* ``RenderMapTile``: ' + Qgis.RenderContextFlag.RenderMapTile.__doc__ + '\n' + '* ``Antialiasing``: ' + Qgis.RenderContextFlag.Antialiasing.__doc__ + '\n' + '* ``RenderPartialOutput``: ' + Qgis.RenderContextFlag.RenderPartialOutput.__doc__ + '\n' + '* ``RenderPreviewJob``: ' + Qgis.RenderContextFlag.RenderPreviewJob.__doc__ + '\n' + '* ``RenderBlocking``: ' + Qgis.RenderContextFlag.RenderBlocking.__doc__ + '\n' + '* ``RenderSymbolPreview``: ' + Qgis.RenderContextFlag.RenderSymbolPreview.__doc__ + '\n' + '* ``LosslessImageRendering``: ' + Qgis.RenderContextFlag.LosslessImageRendering.__doc__ + '\n' + '* ``ApplyScalingWorkaroundForTextRendering``: ' + Qgis.RenderContextFlag.ApplyScalingWorkaroundForTextRendering.__doc__ + '\n' + '* ``Render3DMap``: ' + Qgis.RenderContextFlag.Render3DMap.__doc__ + '\n' + '* ``ApplyClipAfterReprojection``: ' + Qgis.RenderContextFlag.ApplyClipAfterReprojection.__doc__ + '\n' + '* ``RenderingSubSymbol``: ' + Qgis.RenderContextFlag.RenderingSubSymbol.__doc__
# --
QgsRenderContext.Flags = Qgis.RenderContextFlags
Qgis.RenderContextFlag.baseClass = Qgis
Expand Down
1 change: 1 addition & 0 deletions python/core/auto_generated/qgis.sip.in
Expand Up @@ -590,6 +590,7 @@ The development version
ApplyScalingWorkaroundForTextRendering,
Render3DMap,
ApplyClipAfterReprojection,
RenderingSubSymbol,
};
typedef QFlags<Qgis::RenderContextFlag> RenderContextFlags;

Expand Down
1 change: 1 addition & 0 deletions src/core/qgis.h
Expand Up @@ -948,6 +948,7 @@ class CORE_EXPORT Qgis
ApplyScalingWorkaroundForTextRendering = 0x2000, //!< Whether a scaling workaround designed to stablise the rendering of small font sizes (or for painters scaled out by a large amount) when rendering text. Generally this is recommended, but it may incur some performance cost.
Render3DMap = 0x4000, //!< Render is for a 3D map
ApplyClipAfterReprojection = 0x8000, //!< Feature geometry clipping to mapExtent() must be performed after the geometries are transformed using coordinateTransform(). Usually feature geometry clipping occurs using the extent() in the layer's CRS prior to geometry transformation, but in some cases when extent() could not be accurately calculated it is necessary to clip geometries to mapExtent() AFTER transforming them using coordinateTransform().
RenderingSubSymbol = 0x10000, //!< Set whenever a sub-symbol of a parent symbol is currently being rendered. Can be used during symbol and symbol layer rendering to determine whether the symbol being rendered is a subsymbol. (Since QGIS 3.24)
};
//! Render context flags
Q_DECLARE_FLAGS( RenderContextFlags, RenderContextFlag ) SIP_MONKEYPATCH_FLAGS_UNNEST( QgsRenderContext, Flags )
Expand Down
5 changes: 5 additions & 0 deletions src/core/symbology/qgsarrowsymbollayer.cpp
Expand Up @@ -731,6 +731,9 @@ void QgsArrowSymbolLayer::renderPolyline( const QPolygonF &points, QgsSymbolRend
mExpressionScope->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_COUNT, points.size() + 1, true ) );
mExpressionScope->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM, 1, true ) );

const bool prevIsSubsymbol = context.renderContext().flags() & Qgis::RenderContextFlag::RenderingSubSymbol;
context.renderContext().setFlag( Qgis::RenderContextFlag::RenderingSubSymbol );

const double prevOpacity = mSymbol->opacity();
mSymbol->setOpacity( prevOpacity * context.opacity() );

Expand Down Expand Up @@ -840,6 +843,8 @@ void QgsArrowSymbolLayer::renderPolyline( const QPolygonF &points, QgsSymbolRend
}
}

context.renderContext().setFlag( Qgis::RenderContextFlag::RenderingSubSymbol, prevIsSubsymbol );

mSymbol->setOpacity( prevOpacity );
context.renderContext().expressionContext().popScope();
}
Expand Down
16 changes: 16 additions & 0 deletions src/core/symbology/qgsfillsymbollayer.cpp
Expand Up @@ -2971,6 +2971,7 @@ void QgsLinePatternFillSymbolLayer::applyPattern( const QgsSymbolRenderContext &
lineRenderContext.setMapToPixel( mtp );
lineRenderContext.setForceVectorOutput( false );
lineRenderContext.setExpressionContext( context.renderContext().expressionContext() );
lineRenderContext.setFlag( Qgis::RenderContextFlag::RenderingSubSymbol );

fillLineSymbol->startRender( lineRenderContext, context.fields() );

Expand Down Expand Up @@ -3489,6 +3490,7 @@ void QgsPointPatternFillSymbolLayer::applyPattern( const QgsSymbolRenderContext
pointRenderContext.setMapToPixel( mtp );
pointRenderContext.setForceVectorOutput( false );
pointRenderContext.setExpressionContext( context.renderContext().expressionContext() );
pointRenderContext.setFlag( Qgis::RenderContextFlag::RenderingSubSymbol );

mMarkerSymbol->startRender( pointRenderContext, context.fields() );

Expand Down Expand Up @@ -3756,6 +3758,9 @@ void QgsPointPatternFillSymbolLayer::renderPolygon( const QPolygonF &points, con
int pointNum = 0;
const bool needsExpressionContext = hasDataDefinedProperties();

const bool prevIsSubsymbol = context.renderContext().flags() & Qgis::RenderContextFlag::RenderingSubSymbol;
context.renderContext().setFlag( Qgis::RenderContextFlag::RenderingSubSymbol );

bool alternateColumn = false;
int currentCol = -3; // because we actually render a few rows/cols outside the bounds, try to align the col/row numbers to start at 1 for the first visible row/col
for ( double currentX = left; currentX <= right; currentX += width, alternateColumn = !alternateColumn )
Expand Down Expand Up @@ -3839,6 +3844,8 @@ void QgsPointPatternFillSymbolLayer::renderPolygon( const QPolygonF &points, con
}
}
}

context.renderContext().setFlag( Qgis::RenderContextFlag::RenderingSubSymbol, prevIsSubsymbol );
}

QVariantMap QgsPointPatternFillSymbolLayer::properties() const
Expand Down Expand Up @@ -4217,7 +4224,11 @@ void QgsCentroidFillSymbolLayer::render( QgsRenderContext &context, const QVecto
}

QPointF centroid = pointOnSurface ? QgsSymbolLayerUtils::polygonPointOnSurface( part.exterior, &part.rings ) : QgsSymbolLayerUtils::polygonCentroid( part.exterior );

const bool prevIsSubsymbol = context.flags() & Qgis::RenderContextFlag::RenderingSubSymbol;
context.setFlag( Qgis::RenderContextFlag::RenderingSubSymbol );
mMarker->renderPoint( centroid, feature.isValid() ? &feature : nullptr, context, -1, selected );
context.setFlag( Qgis::RenderContextFlag::RenderingSubSymbol, prevIsSubsymbol );

if ( clipPoints )
{
Expand Down Expand Up @@ -4850,13 +4861,18 @@ void QgsRandomMarkerFillSymbolLayer::render( QgsRenderContext &context, const QV
int pointNum = 0;
const bool needsExpressionContext = hasDataDefinedProperties();

const bool prevIsSubsymbol = context.flags() & Qgis::RenderContextFlag::RenderingSubSymbol;
context.setFlag( Qgis::RenderContextFlag::RenderingSubSymbol );

for ( const QgsPointXY &p : std::as_const( randomPoints ) )
{
if ( needsExpressionContext )
scope->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_POINT_NUM, ++pointNum, true ) );
mMarker->renderPoint( QPointF( p.x(), p.y() ), feature.isValid() ? &feature : nullptr, context, -1, selected );
}

context.setFlag( Qgis::RenderContextFlag::RenderingSubSymbol, prevIsSubsymbol );

if ( clipPoints )
{
context.painter()->restore();
Expand Down
5 changes: 5 additions & 0 deletions src/core/symbology/qgsgeometrygeneratorsymbollayer.cpp
Expand Up @@ -446,8 +446,13 @@ void QgsGeometryGeneratorSymbolLayer::render( QgsSymbolRenderContext &context, Q

subSymbolExpressionContextScope->setFeature( f );

const bool prevIsSubsymbol = context.renderContext().flags() & Qgis::RenderContextFlag::RenderingSubSymbol;
context.renderContext().setFlag( Qgis::RenderContextFlag::RenderingSubSymbol );

mSymbol->renderFeature( f, context.renderContext(), -1, context.selected() );

context.renderContext().setFlag( Qgis::RenderContextFlag::RenderingSubSymbol, prevIsSubsymbol );

if ( mRenderingFeature )
mHasRenderedFeature = true;
}
Expand Down
9 changes: 9 additions & 0 deletions src/core/symbology/qgslinesymbollayer.cpp
Expand Up @@ -2518,7 +2518,12 @@ void QgsMarkerLineSymbolLayer::setSymbolAngle( double angle )

void QgsMarkerLineSymbolLayer::renderSymbol( const QPointF &point, const QgsFeature *feature, QgsRenderContext &context, int layer, bool selected )
{
const bool prevIsSubsymbol = context.flags() & Qgis::RenderContextFlag::RenderingSubSymbol;
context.setFlag( Qgis::RenderContextFlag::RenderingSubSymbol );

mMarker->renderPoint( point, feature, context, layer, selected );

context.setFlag( Qgis::RenderContextFlag::RenderingSubSymbol, prevIsSubsymbol );
}

double QgsMarkerLineSymbolLayer::width() const
Expand Down Expand Up @@ -2795,8 +2800,12 @@ void QgsHashedLineSymbolLayer::renderSymbol( const QPointF &point, const QgsFeat
QPolygonF points;
points << QPointF( start.x(), start.y() ) << QPointF( end.x(), end.y() );

const bool prevIsSubsymbol = context.flags() & Qgis::RenderContextFlag::RenderingSubSymbol;
context.setFlag( Qgis::RenderContextFlag::RenderingSubSymbol );

mHashSymbol->renderPolyline( points, feature, context, layer, selected );

context.setFlag( Qgis::RenderContextFlag::RenderingSubSymbol, prevIsSubsymbol );
}

double QgsHashedLineSymbolLayer::hashAngle() const
Expand Down
5 changes: 5 additions & 0 deletions src/core/symbology/qgsmarkersymbollayer.cpp
Expand Up @@ -1913,6 +1913,9 @@ void QgsFilledMarkerSymbolLayer::draw( QgsSymbolRenderContext &context, Qgis::Ma
}
p->setPen( Qt::black );

const bool prevIsSubsymbol = context.renderContext().flags() & Qgis::RenderContextFlag::RenderingSubSymbol;
context.renderContext().setFlag( Qgis::RenderContextFlag::RenderingSubSymbol );

if ( !polygon.isEmpty() )
{
mFill->renderPolygon( polygon, /* rings */ nullptr, context.feature(), context.renderContext(), -1, context.selected() );
Expand All @@ -1923,6 +1926,8 @@ void QgsFilledMarkerSymbolLayer::draw( QgsSymbolRenderContext &context, Qgis::Ma
mFill->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext(), -1, context.selected() );
}

context.renderContext().setFlag( Qgis::RenderContextFlag::RenderingSubSymbol, prevIsSubsymbol );

mFill->setOpacity( prevOpacity );
}

Expand Down
6 changes: 6 additions & 0 deletions src/core/symbology/qgsvectorfieldsymbollayer.cpp
Expand Up @@ -144,13 +144,17 @@ void QgsVectorFieldSymbolLayer::renderPoint( QPointF point, QgsSymbolRenderConte

const QgsRenderContext &ctx = context.renderContext();

const bool prevIsSubsymbol = context.renderContext().flags() & Qgis::RenderContextFlag::RenderingSubSymbol;
context.renderContext().setFlag( Qgis::RenderContextFlag::RenderingSubSymbol );

if ( !context.feature() )
{
//preview
QPolygonF line;
line << QPointF( 0, 50 );
line << QPointF( 100, 50 );
mLineSymbol->renderPolyline( line, nullptr, context.renderContext() );
context.renderContext().setFlag( Qgis::RenderContextFlag::RenderingSubSymbol, prevIsSubsymbol );
return;
}

Expand Down Expand Up @@ -209,7 +213,9 @@ void QgsVectorFieldSymbolLayer::renderPoint( QPointF point, QgsSymbolRenderConte
}

line << destPoint;

mLineSymbol->renderPolyline( line, &f, context.renderContext() );
context.renderContext().setFlag( Qgis::RenderContextFlag::RenderingSubSymbol, prevIsSubsymbol );
}

void QgsVectorFieldSymbolLayer::startRender( QgsSymbolRenderContext &context )
Expand Down

0 comments on commit 40279cb

Please sign in to comment.