Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Ensure that all symbol layer types correctly respect the symbol's opa…
…city

setting, even when the symbol layer has data defined colors set or involves
sub symbols (e.g. marker line symbols)

Fixes #18022
  • Loading branch information
nyalldawson committed Nov 17, 2020
1 parent 0626257 commit 7f9d905
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 19 deletions.
Expand Up @@ -646,7 +646,7 @@ calculating individual symbol angles.
.. seealso:: :py:func:`averageAngleUnit`
%End

virtual void renderPolyline( const QPolygonF &points, QgsSymbolRenderContext &context ) ${SIP_FINAL};
virtual void renderPolyline( const QPolygonF &points, QgsSymbolRenderContext &context );

virtual void renderPolygonStroke( const QPolygonF &points, const QVector<QPolygonF> *rings, QgsSymbolRenderContext &context ) ${SIP_FINAL};

Expand Down Expand Up @@ -795,6 +795,9 @@ Shall the marker be rotated.
Use setRotateSymbols() instead.
%End

virtual void renderPolyline( const QPolygonF &points, QgsSymbolRenderContext &context );


protected:


Expand Down Expand Up @@ -950,6 +953,9 @@ Returns the map unit scale for the hash length.
.. seealso:: :py:func:`hashLength`
%End

virtual void renderPolyline( const QPolygonF &points, QgsSymbolRenderContext &context );


protected:

virtual void setSymbolLineAngle( double angle );
Expand Down
Expand Up @@ -446,6 +446,7 @@ Prepares cache image




private:
virtual void draw( QgsSymbolRenderContext &context, QgsSimpleMarkerSymbolLayerBase::Shape shape, const QPolygonF &polygon, const QPainterPath &path );

Expand Down
7 changes: 7 additions & 0 deletions src/core/symbology/qgsarrowsymbollayer.cpp
Expand Up @@ -693,6 +693,10 @@ void QgsArrowSymbolLayer::renderPolyline( const QPolygonF &points, QgsSymbolRend
context.renderContext().expressionContext().appendScope( mExpressionScope.get() );
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 double prevOpacity = mSymbol->opacity();
mSymbol->setOpacity( prevOpacity * context.opacity() );

if ( isCurved() )
{
_resolveDataDefined( context );
Expand Down Expand Up @@ -793,10 +797,13 @@ void QgsArrowSymbolLayer::renderPolyline( const QPolygonF &points, QgsSymbolRend
QPointF pd( points.at( pIdx + 1 ) );

QPolygonF poly = straightArrow( po, pd, mScaledArrowStartWidth, mScaledArrowWidth, mScaledHeadLength, mScaledHeadThickness, mComputedHeadType, mComputedArrowType, mScaledOffset );

mSymbol->renderPolygon( poly, /* rings */ nullptr, context.feature(), context.renderContext(), -1, context.selected() );
}
}
}

mSymbol->setOpacity( prevOpacity );
context.renderContext().expressionContext().popScope();
}

Expand Down
16 changes: 14 additions & 2 deletions src/core/symbology/qgsellipsesymbollayer.cpp
Expand Up @@ -171,6 +171,14 @@ void QgsEllipseSymbolLayer::renderPoint( QPointF point, QgsSymbolRenderContext &
double scaledWidth = mSymbolWidth;
double scaledHeight = mSymbolHeight;

QColor brushColor = mColor;
brushColor.setAlphaF( brushColor.alphaF() * context.opacity() );
mBrush.setColor( brushColor );

QColor penColor = mStrokeColor;
penColor.setAlphaF( penColor.alphaF() * context.opacity() );
mPen.setColor( penColor );

if ( mDataDefinedProperties.hasActiveProperties() )
{
bool ok;
Expand Down Expand Up @@ -204,10 +212,14 @@ void QgsEllipseSymbolLayer::renderPoint( QPointF point, QgsSymbolRenderContext &
}

context.setOriginalValueVariable( QgsSymbolLayerUtils::encodeColor( mColor ) );
mBrush.setColor( mDataDefinedProperties.valueAsColor( QgsSymbolLayer::PropertyFillColor, context.renderContext().expressionContext(), mColor ) );
QColor brushColor = mDataDefinedProperties.valueAsColor( QgsSymbolLayer::PropertyFillColor, context.renderContext().expressionContext(), mColor );
brushColor.setAlphaF( brushColor.alphaF() * context.opacity() );
mBrush.setColor( brushColor );

context.setOriginalValueVariable( QgsSymbolLayerUtils::encodeColor( mStrokeColor ) );
mPen.setColor( mDataDefinedProperties.valueAsColor( QgsSymbolLayer::PropertyStrokeColor, context.renderContext().expressionContext(), mStrokeColor ) );
QColor penColor = mDataDefinedProperties.valueAsColor( QgsSymbolLayer::PropertyStrokeColor, context.renderContext().expressionContext(), mStrokeColor );
penColor.setAlphaF( penColor.alphaF() * context.opacity() );
mPen.setColor( penColor );

if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyWidth ) || mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyHeight ) || mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyName ) )
{
Expand Down
42 changes: 37 additions & 5 deletions src/core/symbology/qgsfillsymbollayer.cpp
Expand Up @@ -98,7 +98,9 @@ void QgsSimpleFillSymbolLayer::applyDataDefinedSymbology( QgsSymbolRenderContext
if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyFillColor ) )
{
context.setOriginalValueVariable( QgsSymbolLayerUtils::encodeColor( mColor ) );
brush.setColor( mDataDefinedProperties.valueAsColor( QgsSymbolLayer::PropertyFillColor, context.renderContext().expressionContext(), mColor ) );
QColor fillColor = mDataDefinedProperties.valueAsColor( QgsSymbolLayer::PropertyFillColor, context.renderContext().expressionContext(), mColor );
fillColor.setAlphaF( context.opacity() * fillColor.alphaF() );
brush.setColor( fillColor );
}
if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyFillStyle ) )
{
Expand All @@ -110,7 +112,9 @@ void QgsSimpleFillSymbolLayer::applyDataDefinedSymbology( QgsSymbolRenderContext
if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyStrokeColor ) )
{
context.setOriginalValueVariable( QgsSymbolLayerUtils::encodeColor( mStrokeColor ) );
pen.setColor( mDataDefinedProperties.valueAsColor( QgsSymbolLayer::PropertyStrokeColor, context.renderContext().expressionContext(), mStrokeColor ) );
QColor penColor = mDataDefinedProperties.valueAsColor( QgsSymbolLayer::PropertyStrokeColor, context.renderContext().expressionContext(), mStrokeColor );
penColor.setAlphaF( context.opacity() * penColor.alphaF() );
pen.setColor( penColor );
}
if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyStrokeWidth ) )
{
Expand Down Expand Up @@ -277,6 +281,13 @@ void QgsSimpleFillSymbolLayer::renderPolygon( const QPolygonF &points, const QVe
return;
}

QColor fillColor = mColor;
fillColor.setAlphaF( context.opacity() * mColor.alphaF() );
mBrush.setColor( fillColor );
QColor strokeColor = mStrokeColor;
strokeColor.setAlphaF( context.opacity() * mStrokeColor.alphaF() );
mPen.setColor( strokeColor );

applyDataDefinedSymbology( context, mBrush, mPen, mSelPen );

QPointF offset = mOffset;
Expand Down Expand Up @@ -625,6 +636,7 @@ void QgsGradientFillSymbolLayer::applyDataDefinedSymbology( QgsSymbolRenderConte
{
context.setOriginalValueVariable( QgsSymbolLayerUtils::encodeColor( mColor ) );
color = mDataDefinedProperties.valueAsColor( QgsSymbolLayer::PropertyFillColor, context.renderContext().expressionContext(), mColor );
color.setAlphaF( context.opacity() * color.alphaF() );
}

//second gradient color
Expand All @@ -633,6 +645,7 @@ void QgsGradientFillSymbolLayer::applyDataDefinedSymbology( QgsSymbolRenderConte
{
context.setOriginalValueVariable( QgsSymbolLayerUtils::encodeColor( mColor2 ) );
color2 = mDataDefinedProperties.valueAsColor( QgsSymbolLayer::PropertySecondaryColor, context.renderContext().expressionContext(), mColor2 );
color2.setAlphaF( context.opacity() * color2.alphaF() );
}

//gradient rotation angle
Expand Down Expand Up @@ -3739,7 +3752,6 @@ QColor QgsCentroidFillSymbolLayer::color() const

void QgsCentroidFillSymbolLayer::startRender( QgsSymbolRenderContext &context )
{
mMarker->setOpacity( context.opacity() );
mMarker->startRender( context.renderContext(), context.fields() );

mCurrentFeatureId = -1;
Expand All @@ -3762,12 +3774,16 @@ void QgsCentroidFillSymbolLayer::renderPolygon( const QPolygonF &points, const Q
{
// in the middle of rendering a possibly multi-part feature, so we collect all the parts and defer the actual rendering
// until after we've received the final part
mFeatureSymbolOpacity = context.opacity();
mCurrentParts << part;
}
else
{
// not rendering a feature, so we can just render the polygon immediately
const double prevOpacity = mMarker->opacity();
mMarker->setOpacity( mMarker->opacity() * context.opacity() );
render( context.renderContext(), QVector<Part>() << part, context.feature() ? *context.feature() : QgsFeature(), context.selected() );
mMarker->setOpacity( prevOpacity );
}
}

Expand All @@ -3780,7 +3796,13 @@ void QgsCentroidFillSymbolLayer::startFeatureRender( const QgsFeature &, QgsRend
void QgsCentroidFillSymbolLayer::stopFeatureRender( const QgsFeature &feature, QgsRenderContext &context )
{
mRenderingFeature = false;

const double prevOpacity = mMarker->opacity();
mMarker->setOpacity( mMarker->opacity() * mFeatureSymbolOpacity );

render( context, mCurrentParts, feature, false );
mFeatureSymbolOpacity = 1;
mMarker->setOpacity( prevOpacity );
}

void QgsCentroidFillSymbolLayer::render( QgsRenderContext &context, const QVector<QgsCentroidFillSymbolLayer::Part> &parts, const QgsFeature &feature, bool selected )
Expand Down Expand Up @@ -4123,7 +4145,7 @@ void QgsRasterFillSymbolLayer::renderPolygon( const QPolygonF &points, const QVe

void QgsRasterFillSymbolLayer::startRender( QgsSymbolRenderContext &context )
{
applyPattern( mBrush, mImageFilePath, mWidth, mOpacity, context );
applyPattern( mBrush, mImageFilePath, mWidth, mOpacity * context.opacity(), context );
}

void QgsRasterFillSymbolLayer::stopRender( QgsSymbolRenderContext &context )
Expand Down Expand Up @@ -4339,7 +4361,6 @@ QColor QgsRandomMarkerFillSymbolLayer::color() const

void QgsRandomMarkerFillSymbolLayer::startRender( QgsSymbolRenderContext &context )
{
mMarker->setOpacity( context.opacity() );
mMarker->startRender( context.renderContext(), context.fields() );
}

Expand All @@ -4359,12 +4380,16 @@ void QgsRandomMarkerFillSymbolLayer::renderPolygon( const QPolygonF &points, con
{
// in the middle of rendering a possibly multi-part feature, so we collect all the parts and defer the actual rendering
// until after we've received the final part
mFeatureSymbolOpacity = context.opacity();
mCurrentParts << part;
}
else
{
// not rendering a feature, so we can just render the polygon immediately
const double prevOpacity = mMarker->opacity();
mMarker->setOpacity( mMarker->opacity() * context.opacity() );
render( context.renderContext(), QVector< Part>() << part, context.feature() ? *context.feature() : QgsFeature(), context.selected() );
mMarker->setOpacity( prevOpacity );
}
}

Expand Down Expand Up @@ -4600,7 +4625,14 @@ void QgsRandomMarkerFillSymbolLayer::startFeatureRender( const QgsFeature &, Qgs
void QgsRandomMarkerFillSymbolLayer::stopFeatureRender( const QgsFeature &feature, QgsRenderContext &context )
{
mRenderingFeature = false;

const double prevOpacity = mMarker->opacity();
mMarker->setOpacity( mMarker->opacity() * mFeatureSymbolOpacity );

render( context, mCurrentParts, feature, false );

mFeatureSymbolOpacity = 1;
mMarker->setOpacity( prevOpacity );
}


Expand Down
2 changes: 2 additions & 0 deletions src/core/symbology/qgsfillsymbollayer.h
Expand Up @@ -1989,6 +1989,7 @@ class CORE_EXPORT QgsRandomMarkerFillSymbolLayer : public QgsFillSymbolLayer
bool mClipPoints = false;

bool mRenderingFeature = false;
double mFeatureSymbolOpacity = 1;
};


Expand Down Expand Up @@ -2103,6 +2104,7 @@ class CORE_EXPORT QgsCentroidFillSymbolLayer : public QgsFillSymbolLayer
bool mClipOnCurrentPartOnly = false;

bool mRenderingFeature = false;
double mFeatureSymbolOpacity = 1;

QgsFeatureId mCurrentFeatureId = -1;
int mBiggestPartIndex = -1;
Expand Down
30 changes: 24 additions & 6 deletions src/core/symbology/qgslinesymbollayer.cpp
Expand Up @@ -331,6 +331,10 @@ void QgsSimpleLineSymbolLayer::renderPolyline( const QPolygonF &points, QgsSymbo
return;
}

QColor penColor = mColor;
penColor.setAlphaF( mColor.alphaF() * context.opacity() );
mPen.setColor( penColor );

double offset = mOffset;
applyDataDefinedSymbology( context, mPen, mSelPen, offset );

Expand Down Expand Up @@ -563,7 +567,10 @@ void QgsSimpleLineSymbolLayer::applyDataDefinedSymbology( QgsSymbolRenderContext
if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyStrokeColor ) )
{
context.setOriginalValueVariable( QgsSymbolLayerUtils::encodeColor( mColor ) );
pen.setColor( mDataDefinedProperties.valueAsColor( QgsSymbolLayer::PropertyStrokeColor, context.renderContext().expressionContext(), mColor ) );

QColor penColor = mDataDefinedProperties.valueAsColor( QgsSymbolLayer::PropertyStrokeColor, context.renderContext().expressionContext(), mColor );
penColor.setAlphaF( context.opacity() * penColor.alphaF() );
pen.setColor( penColor );
}

//offset
Expand Down Expand Up @@ -2142,8 +2149,6 @@ QColor QgsMarkerLineSymbolLayer::color() const

void QgsMarkerLineSymbolLayer::startRender( QgsSymbolRenderContext &context )
{
mMarker->setOpacity( context.opacity() );

// if being rotated, it gets initialized with every line segment
QgsSymbol::RenderHints hints = QgsSymbol::RenderHints();
if ( rotateSymbols() )
Expand Down Expand Up @@ -2339,6 +2344,14 @@ void QgsMarkerLineSymbolLayer::setDataDefinedProperty( QgsSymbolLayer::Property
QgsLineSymbolLayer::setDataDefinedProperty( key, property );
}

void QgsMarkerLineSymbolLayer::renderPolyline( const QPolygonF &points, QgsSymbolRenderContext &context )
{
const double prevOpacity = mMarker->opacity();
mMarker->setOpacity( mMarker->opacity() * context.opacity() );
QgsTemplatedLineSymbolLayerBase::renderPolyline( points, context );
mMarker->setOpacity( prevOpacity );
}

void QgsMarkerLineSymbolLayer::setSymbolLineAngle( double angle )
{
mMarker->setLineAngle( angle );
Expand Down Expand Up @@ -2449,8 +2462,6 @@ QString QgsHashedLineSymbolLayer::layerType() const

void QgsHashedLineSymbolLayer::startRender( QgsSymbolRenderContext &context )
{
mHashSymbol->setOpacity( context.opacity() );

// if being rotated, it gets initialized with every line segment
QgsSymbol::RenderHints hints = QgsSymbol::RenderHints();
if ( rotateSymbols() )
Expand Down Expand Up @@ -2613,6 +2624,7 @@ void QgsHashedLineSymbolLayer::renderSymbol( const QPointF &point, const QgsFeat
QPolygonF points;
points << QPointF( start.x(), start.y() ) << QPointF( end.x(), end.y() );


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

Expand All @@ -2626,4 +2638,10 @@ void QgsHashedLineSymbolLayer::setHashAngle( double angle )
mHashAngle = angle;
}


void QgsHashedLineSymbolLayer::renderPolyline( const QPolygonF &points, QgsSymbolRenderContext &context )
{
const double prevOpacity = mHashSymbol->opacity();
mHashSymbol->setOpacity( mHashSymbol->opacity() * context.opacity() );
QgsTemplatedLineSymbolLayerBase::renderPolyline( points, context );
mHashSymbol->setOpacity( prevOpacity );
}
6 changes: 5 additions & 1 deletion src/core/symbology/qgslinesymbollayer.h
Expand Up @@ -592,7 +592,7 @@ class CORE_EXPORT QgsTemplatedLineSymbolLayerBase : public QgsLineSymbolLayer
*/
const QgsMapUnitScale &averageAngleMapUnitScale() const { return mAverageAngleLengthMapUnitScale; }

void renderPolyline( const QPolygonF &points, QgsSymbolRenderContext &context ) FINAL;
void renderPolyline( const QPolygonF &points, QgsSymbolRenderContext &context ) override;
void renderPolygonStroke( const QPolygonF &points, const QVector<QPolygonF> *rings, QgsSymbolRenderContext &context ) FINAL;
QgsUnitTypes::RenderUnit outputUnit() const FINAL;
void setMapUnitScale( const QgsMapUnitScale &scale ) FINAL;
Expand Down Expand Up @@ -752,6 +752,8 @@ class CORE_EXPORT QgsMarkerLineSymbolLayer : public QgsTemplatedLineSymbolLayerB
*/
Q_DECL_DEPRECATED void setRotateMarker( bool rotate ) SIP_DEPRECATED { setRotateSymbols( rotate ); }

void renderPolyline( const QPolygonF &points, QgsSymbolRenderContext &context ) override;

protected:

std::unique_ptr< QgsMarkerSymbol > mMarker;
Expand Down Expand Up @@ -876,6 +878,8 @@ class CORE_EXPORT QgsHashedLineSymbolLayer : public QgsTemplatedLineSymbolLayerB
*/
const QgsMapUnitScale &hashLengthMapUnitScale() const { return mHashLengthMapUnitScale; }

void renderPolyline( const QPolygonF &points, QgsSymbolRenderContext &context ) override;

protected:

void setSymbolLineAngle( double angle ) override;
Expand Down

0 comments on commit 7f9d905

Please sign in to comment.