Skip to content

Commit

Permalink
[effects] Fix blur radius not taking dpi into account (fixes #14885)
Browse files Browse the repository at this point in the history
  • Loading branch information
nirvn committed May 23, 2019
1 parent 2170572 commit f9810a4
Show file tree
Hide file tree
Showing 21 changed files with 603 additions and 92 deletions.
78 changes: 73 additions & 5 deletions python/core/auto_generated/effects/qgsblureffect.sip.in
Expand Up @@ -51,28 +51,96 @@ Constructor for QgsBlurEffect.
virtual QgsBlurEffect *clone() const /Factory/;


void setBlurLevel( const int level );
void setBlurLevel( const double level );
%Docstring
Sets blur level (strength)
Sets blur level (radius)

:param level: blur level. Depending on the current blurMethod(), this parameter
has different effects

.. seealso:: :py:func:`blurLevel`

.. seealso:: :py:func:`blurMethod`
.. seealso:: :py:func:`setBlurUnit`

.. seealso:: :py:func:`setBlurMapUnitScale`

.. seealso:: :py:func:`setBlurMethod`
%End

int blurLevel() const;
double blurLevel() const;
%Docstring
Returns the blur level (strength)
Returns the blur level (radius)

:return: blur level. Depending on the current blurMethod(), this parameter
has different effects

.. seealso:: :py:func:`setBlurLevel`

.. seealso:: :py:func:`blurUnit`

.. seealso:: :py:func:`blurMapUnitScale`

.. seealso:: :py:func:`blurMethod`
%End

void setBlurUnit( const QgsUnitTypes::RenderUnit unit );
%Docstring
Sets the units used for the blur level (radius).

:param unit: units for blur level

.. seealso:: :py:func:`blurUnit`

.. seealso:: :py:func:`setBlurLevel`

.. seealso:: :py:func:`setBlurMapUnitScale`

.. versionadded:: 3.4.9
%End

QgsUnitTypes::RenderUnit blurUnit() const;
%Docstring
Returns the units used for the blur level (radius).

:return: units for blur level

.. seealso:: :py:func:`setBlurUnit`

.. seealso:: :py:func:`blurLevel`

.. seealso:: :py:func:`blurMapUnitScale`

.. versionadded:: 3.4.9
%End

void setBlurMapUnitScale( const QgsMapUnitScale &scale );
%Docstring
Sets the map unit scale used for the blur strength (radius).

:param scale: map unit scale for blur strength

.. seealso:: :py:func:`blurMapUnitScale`

.. seealso:: :py:func:`setBlurLevel`

.. seealso:: :py:func:`setBlurUnit`

.. versionadded:: 3.4.9
%End

const QgsMapUnitScale &blurMapUnitScale() const;
%Docstring
Returns the map unit scale used for the blur strength (radius).

:return: map unit scale for blur strength

.. seealso:: :py:func:`setBlurMapUnitScale`

.. seealso:: :py:func:`blurLevel`

.. seealso:: :py:func:`blurUnit`

.. versionadded:: 3.4.9
%End

void setBlurMethod( const BlurMethod method );
Expand Down
82 changes: 74 additions & 8 deletions python/core/auto_generated/effects/qgsgloweffect.sip.in
Expand Up @@ -118,25 +118,91 @@ Returns the map unit scale used for the spread distance.
.. seealso:: :py:func:`spreadUnit`
%End

void setBlurLevel( const int level );
void setBlurLevel( const double level );
%Docstring
Sets blur level (strength) for the glow. This can be used to smooth the
Sets blur level (radius) for the glow. This can be used to smooth the
output from the glow effect.

:param level: blur level. Values between 0 and 16 are valid, with larger
values indicating greater blur strength.
:param level: blur level.

.. seealso:: :py:func:`blurLevel`

.. seealso:: :py:func:`setBlurUnit`

.. seealso:: :py:func:`setBlurMapUnitScale`
%End

double blurLevel() const;
%Docstring
Returns the blur level (radius) for the glow.

:return: blur level.

.. seealso:: :py:func:`setBlurLevel`

.. seealso:: :py:func:`blurUnit`

.. seealso:: :py:func:`blurMapUnitScale`
%End

void setBlurUnit( const QgsUnitTypes::RenderUnit unit );
%Docstring
Sets the units used for the glow blur level (radius).

:param unit: units for blur level

.. seealso:: :py:func:`blurUnit`

.. seealso:: :py:func:`setBlurLevel`

.. seealso:: :py:func:`setBlurMapUnitScale`

.. versionadded:: 3.4.9
%End

QgsUnitTypes::RenderUnit blurUnit() const;
%Docstring
Returns the units used for the glow blur level (radius).

:return: units for blur level

.. seealso:: :py:func:`setBlurUnit`

.. seealso:: :py:func:`blurLevel`

.. seealso:: :py:func:`blurMapUnitScale`

.. versionadded:: 3.4.9
%End

int blurLevel() const;
void setBlurMapUnitScale( const QgsMapUnitScale &scale );
%Docstring
Returns the blur level (strength) for the glow.
Sets the map unit scale used for the glow blur strength (radius).

:return: blur level. Value will be between 0 and 16, with larger
values indicating greater blur strength.
:param scale: map unit scale for blur strength

.. seealso:: :py:func:`blurMapUnitScale`

.. seealso:: :py:func:`setBlurLevel`

.. seealso:: :py:func:`setBlurUnit`

.. versionadded:: 3.4.9
%End

const QgsMapUnitScale &blurMapUnitScale() const;
%Docstring
Returns the map unit scale used for the glow blur strength (radius).

:return: map unit scale for blur strength

.. seealso:: :py:func:`setBlurMapUnitScale`

.. seealso:: :py:func:`blurLevel`

.. seealso:: :py:func:`blurUnit`

.. versionadded:: 3.4.9
%End

void setOpacity( const double opacity );
Expand Down
80 changes: 74 additions & 6 deletions python/core/auto_generated/effects/qgsshadoweffect.sip.in
Expand Up @@ -29,24 +29,92 @@ Base class for paint effects which offset, blurred shadows
virtual void readProperties( const QgsStringMap &props );


void setBlurLevel( const int level );
void setBlurLevel( const double level );
%Docstring
Sets blur level (strength) for the shadow.
Sets blur level (radius) for the shadow.

:param level: blur level. Values between 0 and 16 are valid, with larger
:param level: blur level.
values indicating greater blur strength.

.. seealso:: :py:func:`blurLevel`

.. seealso:: :py:func:`setBlurUnit`

.. seealso:: :py:func:`setBlurMapUnitScale`
%End

int blurLevel() const;
double blurLevel() const;
%Docstring
Returns the blur level (strength) for the shadow.
Returns the blur level (radius) for the shadow.

:return: blur level. Value will be between 0 and 16, with larger
:return: blur level.
values indicating greater blur strength.

.. seealso:: :py:func:`setBlurLevel`

.. seealso:: :py:func:`blurUnit`

.. seealso:: :py:func:`blurMapUnitScale`
%End

void setBlurUnit( const QgsUnitTypes::RenderUnit unit );
%Docstring
Sets the units used for the shadow blur level (radius).

:param unit: units for blur level

.. seealso:: :py:func:`blurUnit`

.. seealso:: :py:func:`setBlurLevel`

.. seealso:: :py:func:`setBlurMapUnitScale`

.. versionadded:: 3.4.9
%End

QgsUnitTypes::RenderUnit blurUnit() const;
%Docstring
Returns the units used for the shadow blur level (radius).

:return: units for blur level

.. seealso:: :py:func:`setBlurUnit`

.. seealso:: :py:func:`blurLevel`

.. seealso:: :py:func:`blurMapUnitScale`

.. versionadded:: 3.4.9
%End

void setBlurMapUnitScale( const QgsMapUnitScale &scale );
%Docstring
Sets the map unit scale used for the shadow blur strength (radius).

:param scale: map unit scale for blur strength

.. seealso:: :py:func:`blurMapUnitScale`

.. seealso:: :py:func:`setBlurLevel`

.. seealso:: :py:func:`setBlurUnit`

.. versionadded:: 3.4.9
%End

const QgsMapUnitScale &blurMapUnitScale() const;
%Docstring
Returns the map unit scale used for the shadow blur strength (radius).

:return: map unit scale for blur strength

.. seealso:: :py:func:`setBlurMapUnitScale`

.. seealso:: :py:func:`blurLevel`

.. seealso:: :py:func:`blurUnit`

.. versionadded:: 3.4.9
%End

void setOffsetAngle( const int angle );
Expand Down
23 changes: 17 additions & 6 deletions src/core/effects/qgsblureffect.cpp
Expand Up @@ -18,6 +18,7 @@
#include "qgsblureffect.h"
#include "qgsimageoperation.h"
#include "qgsrendercontext.h"
#include "qgssymbollayerutils.h"

QgsPaintEffect *QgsBlurEffect::create( const QgsStringMap &map )
{
Expand All @@ -44,14 +45,16 @@ void QgsBlurEffect::draw( QgsRenderContext &context )

void QgsBlurEffect::drawStackBlur( QgsRenderContext &context )
{
int blurLevel = std::round( context.convertToPainterUnits( mBlurLevel, mBlurUnit, mBlurMapUnitScale ) );
QImage im = sourceAsImage( context )->copy();
QgsImageOperation::stackBlur( im, mBlurLevel );
QgsImageOperation::stackBlur( im, blurLevel );
drawBlurredImage( context, im );
}

void QgsBlurEffect::drawGaussianBlur( QgsRenderContext &context )
{
QImage *im = QgsImageOperation::gaussianBlur( *sourceAsImage( context ), mBlurLevel );
int blurLevel = std::round( context.convertToPainterUnits( mBlurLevel, mBlurUnit, mBlurMapUnitScale ) );
QImage *im = QgsImageOperation::gaussianBlur( *sourceAsImage( context ), blurLevel );
drawBlurredImage( context, *im );
delete im;
}
Expand All @@ -76,6 +79,8 @@ QgsStringMap QgsBlurEffect::properties() const
props.insert( QStringLiteral( "blend_mode" ), QString::number( static_cast< int >( mBlendMode ) ) );
props.insert( QStringLiteral( "opacity" ), QString::number( mOpacity ) );
props.insert( QStringLiteral( "blur_level" ), QString::number( mBlurLevel ) );
props.insert( QStringLiteral( "blur_unit" ), QgsUnitTypes::encodeUnit( mBlurUnit ) );
props.insert( QStringLiteral( "blur_unit_scale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mBlurMapUnitScale ) );
props.insert( QStringLiteral( "blur_method" ), QString::number( static_cast< int >( mBlurMethod ) ) );
return props;
}
Expand Down Expand Up @@ -107,11 +112,18 @@ void QgsBlurEffect::readProperties( const QgsStringMap &props )

mEnabled = props.value( QStringLiteral( "enabled" ), QStringLiteral( "1" ) ).toInt();
mDrawMode = static_cast< QgsPaintEffect::DrawMode >( props.value( QStringLiteral( "draw_mode" ), QStringLiteral( "2" ) ).toInt() );
int level = props.value( QStringLiteral( "blur_level" ) ).toInt( &ok );
double level = props.value( QStringLiteral( "blur_level" ) ).toDouble( &ok );
if ( ok )
{
mBlurLevel = level;
if ( !props.contains( QStringLiteral( "blur_unit" ) ) )
{
// deal with pre blur unit era by assuming 96 dpi and converting pixel values as millimeters
mBlurLevel *= 0.2645;
}
}
mBlurUnit = QgsUnitTypes::decodeRenderUnit( props.value( QStringLiteral( "blur_unit" ) ) );
mBlurMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( props.value( QStringLiteral( "blur_unit_scale" ) ) );
QgsBlurEffect::BlurMethod method = static_cast< QgsBlurEffect::BlurMethod >( props.value( QStringLiteral( "blur_method" ) ).toInt( &ok ) );
if ( ok )
{
Expand All @@ -127,9 +139,8 @@ QgsBlurEffect *QgsBlurEffect::clone() const

QRectF QgsBlurEffect::boundingRect( const QRectF &rect, const QgsRenderContext &context ) const
{
Q_UNUSED( context )

int blurLevel = std::round( context.convertToPainterUnits( mBlurLevel, mBlurUnit, mBlurMapUnitScale ) );
//plus possible extension due to blur, with a couple of extra pixels thrown in for safety
double spread = mBlurLevel * 2.0 + 10;
double spread = blurLevel * 2.0 + 10;
return rect.adjusted( -spread, -spread, spread, spread );
}

0 comments on commit f9810a4

Please sign in to comment.