Skip to content

Commit

Permalink
[symbology] Improve rendering of selected SVG markers
Browse files Browse the repository at this point in the history
  • Loading branch information
nirvn committed Aug 26, 2020
1 parent 5e25c06 commit 707bad7
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 65 deletions.
Expand Up @@ -694,6 +694,7 @@ Calculates the marker aspect ratio between width and height.




};


Expand Down
80 changes: 15 additions & 65 deletions src/core/symbology/qgsmarkersymbollayer.cpp
Expand Up @@ -1744,7 +1744,6 @@ void QgsFilledMarkerSymbolLayer::draw( QgsSymbolRenderContext &context, QgsSimpl

QgsSvgMarkerSymbolLayer::QgsSvgMarkerSymbolLayer( const QString &path, double size, double angle, QgsSymbol::ScaleMethod scaleMethod )
{
mPath = path;
mSize = size;
mAngle = angle;
mOffset = QPointF( 0, 0 );
Expand All @@ -1753,7 +1752,7 @@ QgsSvgMarkerSymbolLayer::QgsSvgMarkerSymbolLayer( const QString &path, double si
mStrokeWidthUnit = QgsUnitTypes::RenderMillimeters;
mColor = QColor( 35, 35, 35 );
mStrokeColor = QColor( 35, 35, 35 );
updateDefaultAspectRatio();
setPath( path );
}


Expand All @@ -1775,47 +1774,6 @@ QgsSymbolLayer *QgsSvgMarkerSymbolLayer::create( const QgsStringMap &props )

QgsSvgMarkerSymbolLayer *m = new QgsSvgMarkerSymbolLayer( name, size, angle, scaleMethod );

//we only check the svg default parameters if necessary, since it could be expensive
if ( !props.contains( QStringLiteral( "fill" ) ) && !props.contains( QStringLiteral( "color" ) ) && !props.contains( QStringLiteral( "outline" ) ) &&
!props.contains( QStringLiteral( "outline_color" ) ) && !props.contains( QStringLiteral( "outline-width" ) ) && !props.contains( QStringLiteral( "outline_width" ) ) )
{
QColor fillColor, strokeColor;
double fillOpacity = 1.0;
double strokeOpacity = 1.0;
double strokeWidth;
bool hasFillParam = false, hasFillOpacityParam = false, hasStrokeParam = false, hasStrokeWidthParam = false, hasStrokeOpacityParam = false;
bool hasDefaultFillColor = false, hasDefaultFillOpacity = false, hasDefaultStrokeColor = false, hasDefaultStrokeWidth = false, hasDefaultStrokeOpacity = false;
QgsApplication::svgCache()->containsParams( name, hasFillParam, hasDefaultFillColor, fillColor,
hasFillOpacityParam, hasDefaultFillOpacity, fillOpacity,
hasStrokeParam, hasDefaultStrokeColor, strokeColor,
hasStrokeWidthParam, hasDefaultStrokeWidth, strokeWidth,
hasStrokeOpacityParam, hasDefaultStrokeOpacity, strokeOpacity );
if ( hasDefaultFillColor )
{
m->setFillColor( fillColor );
}
if ( hasDefaultFillOpacity )
{
QColor c = m->fillColor();
c.setAlphaF( fillOpacity );
m->setFillColor( c );
}
if ( hasDefaultStrokeColor )
{
m->setStrokeColor( strokeColor );
}
if ( hasDefaultStrokeWidth )
{
m->setStrokeWidth( strokeWidth );
}
if ( hasDefaultStrokeOpacity )
{
QColor c = m->strokeColor();
c.setAlphaF( strokeOpacity );
m->setStrokeColor( c );
}
}

if ( props.contains( QStringLiteral( "size_unit" ) ) )
m->setSizeUnit( QgsUnitTypes::decodeRenderUnit( props[QStringLiteral( "size_unit" )] ) );
if ( props.contains( QStringLiteral( "size_map_unit_scale" ) ) )
Expand Down Expand Up @@ -1907,12 +1865,13 @@ void QgsSvgMarkerSymbolLayer::resolvePaths( QgsStringMap &properties, const QgsP
void QgsSvgMarkerSymbolLayer::setPath( const QString &path )
{
mDefaultAspectRatio = 0;
mHasFillParam = false;
mPath = path;
QColor defaultFillColor, defaultStrokeColor;
double strokeWidth, fillOpacity, strokeOpacity;
bool hasFillParam = false, hasFillOpacityParam = false, hasStrokeParam = false, hasStrokeWidthParam = false, hasStrokeOpacityParam = false;
bool hasFillOpacityParam = false, hasStrokeParam = false, hasStrokeWidthParam = false, hasStrokeOpacityParam = false;
bool hasDefaultFillColor = false, hasDefaultFillOpacity = false, hasDefaultStrokeColor = false, hasDefaultStrokeWidth = false, hasDefaultStrokeOpacity = false;
QgsApplication::svgCache()->containsParams( path, hasFillParam, hasDefaultFillColor, defaultFillColor,
QgsApplication::svgCache()->containsParams( path, mHasFillParam, hasDefaultFillColor, defaultFillColor,
hasFillOpacityParam, hasDefaultFillOpacity, fillOpacity,
hasStrokeParam, hasDefaultStrokeColor, defaultStrokeColor,
hasStrokeWidthParam, hasDefaultStrokeWidth, strokeWidth,
Expand Down Expand Up @@ -2045,7 +2004,11 @@ void QgsSvgMarkerSymbolLayer::renderPoint( QPointF point, QgsSymbolRenderContext
strokeWidth = context.renderContext().convertToPainterUnits( strokeWidth, mStrokeWidthUnit, mStrokeWidthMapUnitScale );

QColor fillColor = mColor;
if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyFillColor ) )
if ( context.selected() && mHasFillParam )
{
fillColor = context.renderContext().selectionColor();
}
else if ( mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyFillColor ) )
{
context.setOriginalValueVariable( QgsSymbolLayerUtils::encodeColor( mColor ) );
fillColor = mDataDefinedProperties.valueAsColor( QgsSymbolLayer::PropertyFillColor, context.renderContext().expressionContext(), mColor );
Expand All @@ -2060,15 +2023,20 @@ void QgsSvgMarkerSymbolLayer::renderPoint( QPointF point, QgsSymbolRenderContext

bool fitsInCache = true;
bool usePict = true;
bool rasterizeSelected = !mHasFillParam || mDataDefinedProperties.isActive( QgsSymbolLayer::PropertyName );
double hwRatio = 1.0;
if ( !context.renderContext().forceVectorOutput() && !rotated )
if ( ( !context.renderContext().forceVectorOutput() && !rotated ) || ( context.selected() && rasterizeSelected ) )
{
QImage img = QgsApplication::svgCache()->svgAsImage( path, size, fillColor, strokeColor, strokeWidth,
context.renderContext().scaleFactor(), fitsInCache, aspectRatio,
( context.renderContext().flags() & QgsRenderContext::RenderBlocking ) );
if ( fitsInCache && img.width() > 1 )
{
usePict = false;

if ( context.selected() )
QgsImageOperation::adjustHueSaturation( img, 1.0, context.renderContext().selectionColor(), 1.0 );

//consider transparency
if ( !qgsDoubleNear( context.opacity(), 1.0 ) )
{
Expand Down Expand Up @@ -2100,24 +2068,6 @@ void QgsSvgMarkerSymbolLayer::renderPoint( QPointF point, QgsSymbolRenderContext
}
}

if ( context.selected() )
{
QPen pen( context.renderContext().selectionColor() );
double penWidth = context.renderContext().convertToPainterUnits( 1, QgsUnitTypes::RenderMillimeters );
if ( penWidth > size / 20 )
{
// keep the pen width from covering symbol
penWidth = size / 20;
}
double penOffset = penWidth / 2;
pen.setWidth( penWidth );
p->setPen( pen );
p->setBrush( Qt::NoBrush );
double wSize = size + penOffset;
double hSize = size * hwRatio + penOffset;
p->drawRect( QRectF( -wSize / 2.0, -hSize / 2.0, wSize, hSize ) );
}

// workaround issue with nested QPictures forgetting antialiasing flag - see https://github.com/qgis/QGIS/issues/22909
context.renderContext().setPainterFlagsUsingContext( p );
}
Expand Down
2 changes: 2 additions & 0 deletions src/core/symbology/qgsmarkersymbollayer.h
Expand Up @@ -624,8 +624,10 @@ class CORE_EXPORT QgsSvgMarkerSymbolLayer : public QgsMarkerSymbolLayer
double mFixedAspectRatio = 0.0;
//param(fill), param(stroke), param(stroke-width) are going
//to be replaced in memory
bool mHasFillParam = false;
QColor mStrokeColor;
double mStrokeWidth;

QgsUnitTypes::RenderUnit mStrokeWidthUnit;
QgsMapUnitScale mStrokeWidthMapUnitScale;

Expand Down

0 comments on commit 707bad7

Please sign in to comment.