Skip to content
Permalink
Browse files

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 7f9d90536af5b542ad45c41ff97193f974c07f03
@@ -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};

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

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


protected:


@@ -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 );
@@ -446,6 +446,7 @@ Prepares cache image




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

@@ -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 );
@@ -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();
}

@@ -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;
@@ -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 ) )
{
@@ -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 ) )
{
@@ -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 ) )
{
@@ -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;
@@ -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
@@ -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
@@ -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;
@@ -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 );
}
}

@@ -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 )
@@ -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 )
@@ -4339,7 +4361,6 @@ QColor QgsRandomMarkerFillSymbolLayer::color() const

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

@@ -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 );
}
}

@@ -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 );
}


@@ -1989,6 +1989,7 @@ class CORE_EXPORT QgsRandomMarkerFillSymbolLayer : public QgsFillSymbolLayer
bool mClipPoints = false;

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


@@ -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;
@@ -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 );

@@ -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
@@ -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() )
@@ -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 );
@@ -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() )
@@ -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 );
}

@@ -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 );
}
@@ -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;
@@ -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;
@@ -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;

0 comments on commit 7f9d905

Please sign in to comment.
You can’t perform that action at this time.