[effects] Fix blur radius not taking dpi into account (fixes #14885)

This commit is contained in:
nirvn 2019-05-22 13:20:13 +07:00 committed by Mathieu Pellerin
parent 217057236a
commit f9810a4534
21 changed files with 603 additions and 92 deletions

View File

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

View File

@ -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
int blurLevel() const;
double blurLevel() const;
%Docstring
Returns the blur level (strength) for the glow.
Returns the blur level (radius) for the glow.
:return: blur level. Value will be between 0 and 16, with larger
values indicating greater blur strength.
: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
void setBlurMapUnitScale( const QgsMapUnitScale &scale );
%Docstring
Sets the map unit scale used for the glow 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 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 );

View File

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

View File

@ -18,6 +18,7 @@
#include "qgsblureffect.h"
#include "qgsimageoperation.h"
#include "qgsrendercontext.h"
#include "qgssymbollayerutils.h"
QgsPaintEffect *QgsBlurEffect::create( const QgsStringMap &map )
{
@ -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;
}
@ -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;
}
@ -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 )
{
@ -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 );
}

View File

@ -61,22 +61,66 @@ class CORE_EXPORT QgsBlurEffect : public QgsPaintEffect
QgsBlurEffect *clone() const override SIP_FACTORY;
/**
* Sets blur level (strength)
* Sets blur level (radius)
* \param level blur level. Depending on the current blurMethod(), this parameter
* has different effects
* \see blurLevel
* \see blurMethod
* \see setBlurUnit
* \see setBlurMapUnitScale
* \see setBlurMethod
*/
void setBlurLevel( const int level ) { mBlurLevel = level; }
void setBlurLevel( const double level ) { mBlurLevel = level; }
/**
* Returns the blur level (strength)
* Returns the blur level (radius)
* \returns blur level. Depending on the current blurMethod(), this parameter
* has different effects
* \see setBlurLevel
* \see blurUnit
* \see blurMapUnitScale
* \see blurMethod
*/
int blurLevel() const { return mBlurLevel; }
double blurLevel() const { return mBlurLevel; }
/**
* Sets the units used for the blur level (radius).
* \param unit units for blur level
* \see blurUnit
* \see setBlurLevel
* \see setBlurMapUnitScale
* \since QGIS 3.4.9
*/
void setBlurUnit( const QgsUnitTypes::RenderUnit unit ) { mBlurUnit = unit; }
/**
* Returns the units used for the blur level (radius).
* \returns units for blur level
* \see setBlurUnit
* \see blurLevel
* \see blurMapUnitScale
* \since QGIS 3.4.9
*/
QgsUnitTypes::RenderUnit blurUnit() const { return mBlurUnit; }
/**
* Sets the map unit scale used for the blur strength (radius).
* \param scale map unit scale for blur strength
* \see blurMapUnitScale
* \see setBlurLevel
* \see setBlurUnit
* \since QGIS 3.4.9
*/
void setBlurMapUnitScale( const QgsMapUnitScale &scale ) { mBlurMapUnitScale = scale; }
/**
* Returns the map unit scale used for the blur strength (radius).
* \returns map unit scale for blur strength
* \see setBlurMapUnitScale
* \see blurLevel
* \see blurUnit
* \since QGIS 3.4.9
*/
const QgsMapUnitScale &blurMapUnitScale() const { return mBlurMapUnitScale; }
/**
* Sets the blur method (algorithm) to use for performing the blur.
@ -131,7 +175,9 @@ class CORE_EXPORT QgsBlurEffect : public QgsPaintEffect
private:
int mBlurLevel = 10;
double mBlurLevel = 2.645;
QgsUnitTypes::RenderUnit mBlurUnit = QgsUnitTypes::RenderMillimeters;
QgsMapUnitScale mBlurMapUnitScale;
BlurMethod mBlurMethod = StackBlur;
double mOpacity = 1.0;
QPainter::CompositionMode mBlendMode = QPainter::CompositionMode_SourceOver;

View File

@ -78,9 +78,16 @@ void QgsGlowEffect::draw( QgsRenderContext &context )
dtProps.ramp = ramp;
QgsImageOperation::distanceTransform( im, dtProps );
if ( mBlurLevel > 0 )
int blurLevel = std::round( context.convertToPainterUnits( mBlurLevel, mBlurUnit, mBlurMapUnitScale ) );
if ( blurLevel <= 16 )
{
QgsImageOperation::stackBlur( im, mBlurLevel );
QgsImageOperation::stackBlur( im, blurLevel );
}
else
{
QImage *imb = QgsImageOperation::gaussianBlur( im, blurLevel );
im = QImage( *imb );
delete imb;
}
QgsImageOperation::multiplyOpacity( im, mOpacity );
@ -110,6 +117,8 @@ QgsStringMap QgsGlowEffect::properties() const
props.insert( QStringLiteral( "blend_mode" ), QString::number( 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( "spread" ), QString::number( mSpread ) );
props.insert( QStringLiteral( "spread_unit" ), QgsUnitTypes::encodeUnit( mSpreadUnit ) );
props.insert( QStringLiteral( "spread_unit_scale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mSpreadMapUnitScale ) );
@ -150,11 +159,18 @@ void QgsGlowEffect::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" ) ) );
double spread = props.value( QStringLiteral( "spread" ) ).toDouble( &ok );
if ( ok )
{
@ -210,10 +226,11 @@ QgsGlowEffect &QgsGlowEffect::operator=( const QgsGlowEffect &rhs )
QRectF QgsGlowEffect::boundingRect( const QRectF &rect, const QgsRenderContext &context ) const
{
//spread size
//blur radius and spread size
int blurLevel = std::round( context.convertToPainterUnits( mBlurLevel, mBlurUnit, mBlurMapUnitScale ) );
double spread = context.convertToPainterUnits( mSpread, mSpreadUnit, mSpreadMapUnitScale );
//plus possible extension due to blur, with a couple of extra pixels thrown in for safety
spread += mBlurLevel * 2 + 10;
spread += blurLevel * 2 + 10;
return rect.adjusted( -spread, -spread, spread, spread );
}

View File

@ -109,21 +109,63 @@ class CORE_EXPORT QgsGlowEffect : public QgsPaintEffect
const QgsMapUnitScale &spreadMapUnitScale() const { return mSpreadMapUnitScale; }
/**
* 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.
* \see blurLevel
* \see setBlurUnit
* \see setBlurMapUnitScale
*/
void setBlurLevel( const int level ) { mBlurLevel = level; }
void setBlurLevel( const double level ) { mBlurLevel = level; }
/**
* Returns the blur level (strength) for the glow.
* \returns blur level. Value will be between 0 and 16, with larger
* values indicating greater blur strength.
* Returns the blur level (radius) for the glow.
* \returns blur level.
* \see setBlurLevel
* \see blurUnit
* \see blurMapUnitScale
*/
int blurLevel() const { return mBlurLevel; }
double blurLevel() const { return mBlurLevel; }
/**
* Sets the units used for the glow blur level (radius).
* \param unit units for blur level
* \see blurUnit
* \see setBlurLevel
* \see setBlurMapUnitScale
* \since QGIS 3.4.9
*/
void setBlurUnit( const QgsUnitTypes::RenderUnit unit ) { mBlurUnit = unit; }
/**
* Returns the units used for the glow blur level (radius).
* \returns units for blur level
* \see setBlurUnit
* \see blurLevel
* \see blurMapUnitScale
* \since QGIS 3.4.9
*/
QgsUnitTypes::RenderUnit blurUnit() const { return mBlurUnit; }
/**
* Sets the map unit scale used for the glow blur strength (radius).
* \param scale map unit scale for blur strength
* \see blurMapUnitScale
* \see setBlurLevel
* \see setBlurUnit
* \since QGIS 3.4.9
*/
void setBlurMapUnitScale( const QgsMapUnitScale &scale ) { mBlurMapUnitScale = scale; }
/**
* Returns the map unit scale used for the glow blur strength (radius).
* \returns map unit scale for blur strength
* \see setBlurMapUnitScale
* \see blurLevel
* \see blurUnit
* \since QGIS 3.4.9
*/
const QgsMapUnitScale &blurMapUnitScale() const { return mBlurMapUnitScale; }
/**
* Sets the \a opacity for the effect.
@ -235,7 +277,9 @@ class CORE_EXPORT QgsGlowEffect : public QgsPaintEffect
QgsUnitTypes::RenderUnit mSpreadUnit = QgsUnitTypes::RenderMillimeters;
QgsMapUnitScale mSpreadMapUnitScale;
QgsColorRamp *mRamp = nullptr;
int mBlurLevel = 3;
double mBlurLevel = 2.645;
QgsUnitTypes::RenderUnit mBlurUnit = QgsUnitTypes::RenderMillimeters;
QgsMapUnitScale mBlurMapUnitScale;
double mOpacity = 0.5;
QColor mColor;
QPainter::CompositionMode mBlendMode = QPainter::CompositionMode_SourceOver;

View File

@ -45,7 +45,18 @@ void QgsShadowEffect::draw( QgsRenderContext &context )
}
QgsImageOperation::overlayColor( colorisedIm, mColor );
QgsImageOperation::stackBlur( colorisedIm, mBlurLevel );
int blurLevel = std::round( context.convertToPainterUnits( mBlurLevel, mBlurUnit, mBlurMapUnitScale ) );
if ( blurLevel <= 16 )
{
QgsImageOperation::stackBlur( colorisedIm, blurLevel );
}
else
{
QImage *imb = QgsImageOperation::gaussianBlur( colorisedIm, blurLevel );
colorisedIm = QImage( *imb );
delete imb;
}
double offsetDist = context.convertToPainterUnits( mOffsetDist, mOffsetUnit, mOffsetMapUnitScale );
@ -88,6 +99,8 @@ QgsStringMap QgsShadowEffect::properties() const
props.insert( QStringLiteral( "blend_mode" ), QString::number( 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( "offset_angle" ), QString::number( mOffsetAngle ) );
props.insert( QStringLiteral( "offset_distance" ), QString::number( mOffsetDist ) );
props.insert( QStringLiteral( "offset_unit" ), QgsUnitTypes::encodeUnit( mOffsetUnit ) );
@ -122,11 +135,18 @@ void QgsShadowEffect::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" ) ) );
int angle = props.value( QStringLiteral( "offset_angle" ) ).toInt( &ok );
if ( ok )
{
@ -147,10 +167,11 @@ void QgsShadowEffect::readProperties( const QgsStringMap &props )
QRectF QgsShadowEffect::boundingRect( const QRectF &rect, const QgsRenderContext &context ) const
{
//offset distance
//blur radius and offset distance
int blurLevel = std::round( context.convertToPainterUnits( mBlurLevel, mBlurUnit, mBlurMapUnitScale ) );
double spread = context.convertToPainterUnits( mOffsetDist, mOffsetUnit, mOffsetMapUnitScale );
//plus possible extension due to blur, with a couple of extra pixels thrown in for safety
spread += mBlurLevel * 2 + 10;
spread += blurLevel * 2 + 10;
return rect.adjusted( -spread, -spread, spread, spread );
}

View File

@ -42,20 +42,64 @@ class CORE_EXPORT QgsShadowEffect : public QgsPaintEffect
void readProperties( const QgsStringMap &props ) override;
/**
* Sets blur level (strength) for the shadow.
* \param level blur level. Values between 0 and 16 are valid, with larger
* Sets blur level (radius) for the shadow.
* \param level blur level.
* values indicating greater blur strength.
* \see blurLevel
* \see setBlurUnit
* \see setBlurMapUnitScale
*/
void setBlurLevel( const int level ) { mBlurLevel = level; }
void setBlurLevel( const double level ) { mBlurLevel = level; }
/**
* Returns the blur level (strength) for the shadow.
* \returns blur level. Value will be between 0 and 16, with larger
* Returns the blur level (radius) for the shadow.
* \returns blur level.
* values indicating greater blur strength.
* \see setBlurLevel
* \see blurUnit
* \see blurMapUnitScale
*/
int blurLevel() const { return mBlurLevel; }
double blurLevel() const { return mBlurLevel; }
/**
* Sets the units used for the shadow blur level (radius).
* \param unit units for blur level
* \see blurUnit
* \see setBlurLevel
* \see setBlurMapUnitScale
* \since QGIS 3.4.9
*/
void setBlurUnit( const QgsUnitTypes::RenderUnit unit ) { mBlurUnit = unit; }
/**
* Returns the units used for the shadow blur level (radius).
* \returns units for blur level
* \see setBlurUnit
* \see blurLevel
* \see blurMapUnitScale
* \since QGIS 3.4.9
*/
QgsUnitTypes::RenderUnit blurUnit() const { return mBlurUnit; }
/**
* Sets the map unit scale used for the shadow blur strength (radius).
* \param scale map unit scale for blur strength
* \see blurMapUnitScale
* \see setBlurLevel
* \see setBlurUnit
* \since QGIS 3.4.9
*/
void setBlurMapUnitScale( const QgsMapUnitScale &scale ) { mBlurMapUnitScale = scale; }
/**
* Returns the map unit scale used for the shadow blur strength (radius).
* \returns map unit scale for blur strength
* \see setBlurMapUnitScale
* \see blurLevel
* \see blurUnit
* \since QGIS 3.4.9
*/
const QgsMapUnitScale &blurMapUnitScale() const { return mBlurMapUnitScale; }
/**
* Sets the angle for offsetting the shadow.
@ -186,7 +230,9 @@ class CORE_EXPORT QgsShadowEffect : public QgsPaintEffect
*/
virtual bool exteriorShadow() const = 0;
int mBlurLevel = 10;
double mBlurLevel = 2.645;
QgsUnitTypes::RenderUnit mBlurUnit = QgsUnitTypes::RenderMillimeters;
QgsMapUnitScale mBlurMapUnitScale;
int mOffsetAngle = 135;
double mOffsetDist = 2.0;
QgsUnitTypes::RenderUnit mOffsetUnit = QgsUnitTypes::RenderMillimeters;

View File

@ -117,12 +117,16 @@ QgsBlurWidget::QgsBlurWidget( QWidget *parent )
{
setupUi( this );
connect( mBlurTypeCombo, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsBlurWidget::mBlurTypeCombo_currentIndexChanged );
connect( mBlurStrengthSpnBx, static_cast< void ( QSpinBox::* )( int ) >( &QSpinBox::valueChanged ), this, &QgsBlurWidget::mBlurStrengthSpnBx_valueChanged );
connect( mBlurStrengthSpnBx, static_cast< void ( QDoubleSpinBox::* )( double ) >( &QDoubleSpinBox::valueChanged ), this, &QgsBlurWidget::mBlurStrengthSpnBx_valueChanged );
connect( mBlurUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsBlurWidget::mBlurUnitWidget_changed );
connect( mDrawModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsBlurWidget::mDrawModeComboBox_currentIndexChanged );
connect( mBlendCmbBx, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsBlurWidget::mBlendCmbBx_currentIndexChanged );
mBlurTypeCombo->addItem( tr( "Stack blur (fast)" ), QgsBlurEffect::StackBlur );
mBlurTypeCombo->addItem( tr( "Gaussian blur (quality)" ), QgsBlurEffect::GaussianBlur );
mBlurTypeCombo->addItem( tr( "Stack blur (fast, doesn't support high dpi)" ), QgsBlurEffect::StackBlur );
mBlurTypeCombo->addItem( tr( "Gaussian blur (quality, supports high dpi)" ), QgsBlurEffect::GaussianBlur );
mBlurUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderPixels << QgsUnitTypes::RenderMapUnits
<< QgsUnitTypes::RenderPoints << QgsUnitTypes::RenderInches );
initGui();
connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, &QgsBlurWidget::opacityChanged );
@ -187,7 +191,7 @@ void QgsBlurWidget::mBlurTypeCombo_currentIndexChanged( int index )
emit changed();
}
void QgsBlurWidget::mBlurStrengthSpnBx_valueChanged( int value )
void QgsBlurWidget::mBlurStrengthSpnBx_valueChanged( double value )
{
if ( !mEffect )
return;
@ -196,6 +200,18 @@ void QgsBlurWidget::mBlurStrengthSpnBx_valueChanged( int value )
emit changed();
}
void QgsBlurWidget::mBlurUnitWidget_changed()
{
if ( !mEffect )
{
return;
}
mEffect->setBlurUnit( mBlurUnitWidget->unit() );
mEffect->setBlurMapUnitScale( mBlurUnitWidget->getMapUnitScale() );
emit changed();
}
void QgsBlurWidget::opacityChanged( double value )
{
if ( !mEffect )
@ -244,7 +260,8 @@ QgsShadowEffectWidget::QgsShadowEffectWidget( QWidget *parent )
connect( mShadowColorBtn, &QgsColorButton::colorChanged, this, &QgsShadowEffectWidget::mShadowColorBtn_colorChanged );
connect( mDrawModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsShadowEffectWidget::mDrawModeComboBox_currentIndexChanged );
connect( mShadowBlendCmbBx, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsShadowEffectWidget::mShadowBlendCmbBx_currentIndexChanged );
connect( mShadowRadiuSpnBx, static_cast< void ( QSpinBox::* )( int ) >( &QSpinBox::valueChanged ), this, &QgsShadowEffectWidget::mShadowRadiuSpnBx_valueChanged );
connect( mShadowRadiuSpnBx, static_cast< void ( QDoubleSpinBox::* )( double ) >( &QDoubleSpinBox::valueChanged ), this, &QgsShadowEffectWidget::mShadowRadiuSpnBx_valueChanged );
connect( mBlurUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsShadowEffectWidget::mBlurUnitWidget_changed );
mShadowColorBtn->setAllowOpacity( false );
mShadowColorBtn->setColorDialogTitle( tr( "Select Shadow Color" ) );
@ -253,6 +270,8 @@ QgsShadowEffectWidget::QgsShadowEffectWidget( QWidget *parent )
mOffsetUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderPixels << QgsUnitTypes::RenderMapUnits
<< QgsUnitTypes::RenderPoints << QgsUnitTypes::RenderInches );
mBlurUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderPixels << QgsUnitTypes::RenderMapUnits
<< QgsUnitTypes::RenderPoints << QgsUnitTypes::RenderInches );
initGui();
@ -283,6 +302,8 @@ void QgsShadowEffectWidget::initGui()
mOffsetUnitWidget->setUnit( mEffect->offsetUnit() );
mOffsetUnitWidget->setMapUnitScale( mEffect->offsetMapUnitScale() );
mShadowRadiuSpnBx->setValue( mEffect->blurLevel() );
mBlurUnitWidget->setUnit( mEffect->blurUnit() );
mBlurUnitWidget->setMapUnitScale( mEffect->blurMapUnitScale() );
mOpacityWidget->setOpacity( mEffect->opacity() );
mShadowColorBtn->setColor( mEffect->color() );
mShadowBlendCmbBx->setBlendMode( mEffect->blendMode() );
@ -298,6 +319,7 @@ void QgsShadowEffectWidget::blockSignals( const bool block )
mShadowOffsetSpnBx->blockSignals( block );
mOffsetUnitWidget->blockSignals( block );
mShadowRadiuSpnBx->blockSignals( block );
mBlurUnitWidget->blockSignals( block );
mOpacityWidget->blockSignals( block );
mShadowColorBtn->blockSignals( block );
mShadowBlendCmbBx->blockSignals( block );
@ -361,7 +383,7 @@ void QgsShadowEffectWidget::mShadowColorBtn_colorChanged( const QColor &color )
emit changed();
}
void QgsShadowEffectWidget::mShadowRadiuSpnBx_valueChanged( int value )
void QgsShadowEffectWidget::mShadowRadiuSpnBx_valueChanged( double value )
{
if ( !mEffect )
return;
@ -370,6 +392,18 @@ void QgsShadowEffectWidget::mShadowRadiuSpnBx_valueChanged( int value )
emit changed();
}
void QgsShadowEffectWidget::mBlurUnitWidget_changed()
{
if ( !mEffect )
{
return;
}
mEffect->setBlurUnit( mBlurUnitWidget->unit() );
mEffect->setBlurMapUnitScale( mBlurUnitWidget->getMapUnitScale() );
emit changed();
}
void QgsShadowEffectWidget::mDrawModeComboBox_currentIndexChanged( int index )
{
Q_UNUSED( index )
@ -408,7 +442,8 @@ QgsGlowWidget::QgsGlowWidget( QWidget *parent )
connect( mColorBtn, &QgsColorButton::colorChanged, this, &QgsGlowWidget::mColorBtn_colorChanged );
connect( mBlendCmbBx, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGlowWidget::mBlendCmbBx_currentIndexChanged );
connect( mDrawModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGlowWidget::mDrawModeComboBox_currentIndexChanged );
connect( mBlurRadiusSpnBx, static_cast< void ( QSpinBox::* )( int ) >( &QSpinBox::valueChanged ), this, &QgsGlowWidget::mBlurRadiusSpnBx_valueChanged );
connect( mBlurRadiusSpnBx, static_cast< void ( QDoubleSpinBox::* )( double ) >( &QDoubleSpinBox::valueChanged ), this, &QgsGlowWidget::mBlurRadiusSpnBx_valueChanged );
connect( mBlurUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsGlowWidget::mBlurUnitWidget_changed );
mColorBtn->setAllowOpacity( false );
mColorBtn->setColorDialogTitle( tr( "Select Glow Color" ) );
@ -416,6 +451,8 @@ QgsGlowWidget::QgsGlowWidget( QWidget *parent )
mSpreadUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderPixels << QgsUnitTypes::RenderMapUnits
<< QgsUnitTypes::RenderPoints << QgsUnitTypes::RenderInches );
mBlurUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderPixels << QgsUnitTypes::RenderMapUnits
<< QgsUnitTypes::RenderPoints << QgsUnitTypes::RenderInches );
btnColorRamp->setShowGradientOnly( true );
@ -538,7 +575,7 @@ void QgsGlowWidget::mColorBtn_colorChanged( const QColor &color )
emit changed();
}
void QgsGlowWidget::mBlurRadiusSpnBx_valueChanged( int value )
void QgsGlowWidget::mBlurRadiusSpnBx_valueChanged( double value )
{
if ( !mEffect )
return;
@ -547,6 +584,18 @@ void QgsGlowWidget::mBlurRadiusSpnBx_valueChanged( int value )
emit changed();
}
void QgsGlowWidget::mBlurUnitWidget_changed()
{
if ( !mEffect )
{
return;
}
mEffect->setBlurUnit( mBlurUnitWidget->unit() );
mEffect->setBlurMapUnitScale( mBlurUnitWidget->getMapUnitScale() );
emit changed();
}
void QgsGlowWidget::mBlendCmbBx_currentIndexChanged( int index )
{
Q_UNUSED( index )

View File

@ -120,7 +120,8 @@ class GUI_EXPORT QgsBlurWidget : public QgsPaintEffectWidget, private Ui::Widget
private slots:
void mBlurTypeCombo_currentIndexChanged( int index );
void mBlurStrengthSpnBx_valueChanged( int value );
void mBlurStrengthSpnBx_valueChanged( double value );
void mBlurUnitWidget_changed();
void opacityChanged( double value );
void mDrawModeComboBox_currentIndexChanged( int index );
void mBlendCmbBx_currentIndexChanged( int index );
@ -161,7 +162,8 @@ class GUI_EXPORT QgsShadowEffectWidget : public QgsPaintEffectWidget, private Ui
void mShadowColorBtn_colorChanged( const QColor &color );
void mDrawModeComboBox_currentIndexChanged( int index );
void mShadowBlendCmbBx_currentIndexChanged( int index );
void mShadowRadiuSpnBx_valueChanged( int value );
void mShadowRadiuSpnBx_valueChanged( double value );
void mBlurUnitWidget_changed();
};
@ -196,7 +198,8 @@ class GUI_EXPORT QgsGlowWidget : public QgsPaintEffectWidget, private Ui::Widget
void mColorBtn_colorChanged( const QColor &color );
void mBlendCmbBx_currentIndexChanged( int index );
void mDrawModeComboBox_currentIndexChanged( int index );
void mBlurRadiusSpnBx_valueChanged( int value );
void mBlurRadiusSpnBx_valueChanged( double value );
void mBlurUnitWidget_changed();
void applyColorRamp();
};

View File

@ -31,7 +31,7 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="1">
<item row="0" column="1" colspan="2">
<widget class="QComboBox" name="mBlurTypeCombo"/>
</item>
<item row="2" column="0">
@ -48,19 +48,41 @@
</property>
</widget>
</item>
<item row="3" column="1">
<item row="3" column="1" colspan="2">
<widget class="QgsBlendModeComboBox" name="mBlendCmbBx"/>
</item>
<item row="1" column="1">
<widget class="QgsSpinBox" name="mBlurStrengthSpnBx">
<widget class="QgsDoubleSpinBox" name="mBlurStrengthSpnBx">
<property name="decimals">
<number>4</number>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<number>16</number>
<double>9999999.000000000000000</double>
</property>
<property name="singleStep">
<double>0.200000000000000</double>
</property>
<property name="showClearButton" stdset="0">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QgsUnitSelectionWidget" name="mBlurUnitWidget" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
@ -75,7 +97,7 @@
</property>
</widget>
</item>
<item row="4" column="1">
<item row="4" column="1" colspan="2">
<widget class="QgsEffectDrawModeComboBox" name="mDrawModeComboBox"/>
</item>
<item row="4" column="0">
@ -85,7 +107,7 @@
</property>
</widget>
</item>
<item row="2" column="1">
<item row="2" column="1" colspan="2">
<widget class="QgsOpacityWidget" name="mOpacityWidget" native="true">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
@ -114,9 +136,9 @@
</widget>
<customwidgets>
<customwidget>
<class>QgsSpinBox</class>
<extends>QSpinBox</extends>
<header>qgsspinbox.h</header>
<class>QgsDoubleSpinBox</class>
<extends>QDoubleSpinBox</extends>
<header>qgsdoublespinbox.h</header>
</customwidget>
<customwidget>
<class>QgsBlendModeComboBox</class>

View File

@ -84,6 +84,9 @@
<property name="maximum">
<double>9999999.000000000000000</double>
</property>
<property name="singleStep">
<double>0.200000000000000</double>
</property>
<property name="showClearButton" stdset="0">
<bool>false</bool>
</property>
@ -102,16 +105,38 @@
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QgsSpinBox" name="mBlurRadiusSpnBx">
<item row="1" column="1">
<widget class="QgsDoubleSpinBox" name="mBlurRadiusSpnBx">
<property name="decimals">
<number>4</number>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<number>16</number>
<double>9999999.000000000000000</double>
</property>
<property name="singleStep">
<double>0.200000000000000</double>
</property>
<property name="showClearButton" stdset="0">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QgsUnitSelectionWidget" name="mBlurUnitWidget" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
</widget>
</item>
<item row="4" column="1" colspan="2">
<widget class="QgsColorRampButton" name="btnColorRamp">
<property name="sizePolicy">

View File

@ -42,6 +42,9 @@
<property name="maximum">
<double>9999999.000000000000000</double>
</property>
<property name="singleStep">
<double>0.200000000000000</double>
</property>
<property name="showClearButton" stdset="0">
<bool>false</bool>
</property>
@ -107,16 +110,38 @@
<item row="5" column="1" colspan="2">
<widget class="QgsBlendModeComboBox" name="mShadowBlendCmbBx"/>
</item>
<item row="2" column="1" colspan="2">
<widget class="QgsSpinBox" name="mShadowRadiuSpnBx">
<item row="2" column="1">
<widget class="QgsDoubleSpinBox" name="mShadowRadiuSpnBx">
<property name="decimals">
<number>4</number>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<number>16</number>
<double>9999999.000000000000000</double>
</property>
<property name="singleStep">
<double>0.200000000000000</double>
</property>
<property name="showClearButton" stdset="0">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QgsUnitSelectionWidget" name="mBlurUnitWidget" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_24">
<item>

View File

@ -360,8 +360,8 @@ void TestQgsPaintEffect::blur()
QCOMPARE( effect->opacity(), 0.5 );
effect->setEnabled( false );
QCOMPARE( effect->enabled(), false );
effect->setBlurLevel( 6 );
QCOMPARE( effect->blurLevel(), 6 );
effect->setBlurLevel( 6.0 );
QCOMPARE( effect->blurLevel(), 6.0 );
effect->setBlurMethod( QgsBlurEffect::GaussianBlur );
QCOMPARE( effect->blurMethod(), QgsBlurEffect::GaussianBlur );
effect->setDrawMode( QgsPaintEffect::Modifier );
@ -434,8 +434,8 @@ void TestQgsPaintEffect::dropShadow()
QCOMPARE( effect->opacity(), 0.5 );
effect->setEnabled( false );
QCOMPARE( effect->enabled(), false );
effect->setBlurLevel( 6 );
QCOMPARE( effect->blurLevel(), 6 );
effect->setBlurLevel( 6.0 );
QCOMPARE( effect->blurLevel(), 6.0 );
effect->setOffsetAngle( 77 );
QCOMPARE( effect->offsetAngle(), 77 );
effect->setOffsetDistance( 9.7 );
@ -531,8 +531,8 @@ void TestQgsPaintEffect::glow()
QCOMPARE( effect->opacity(), 0.5 );
effect->setEnabled( false );
QCOMPARE( effect->enabled(), false );
effect->setBlurLevel( 6 );
QCOMPARE( effect->blurLevel(), 6 );
effect->setBlurLevel( 6.0 );
QCOMPARE( effect->blurLevel(), 6.0 );
effect->setSpread( 7.8 );
QCOMPARE( effect->spread(), 7.8 );
effect->setSpreadUnit( QgsUnitTypes::RenderMapUnits );

View File

@ -41,7 +41,7 @@ class PyQgsTextFormatWidget(unittest.TestCase):
s.setOpacity(0.5)
s.setJoinStyle(Qt.RoundJoin)
s.setBlendMode(QPainter.CompositionMode_Difference)
s.setPaintEffect(QgsBlurEffect.create({'blur_level': '10', 'enabled': '1'}))
s.setPaintEffect(QgsBlurEffect.create({'blur_level': '2.0', 'blur_unit': QgsUnitTypes.encodeUnit(QgsUnitTypes.RenderMillimeters), 'enabled': '1'}))
return s
def checkBufferSettings(self, s):
@ -56,7 +56,7 @@ class PyQgsTextFormatWidget(unittest.TestCase):
self.assertEqual(s.joinStyle(), Qt.RoundJoin)
self.assertEqual(s.blendMode(), QPainter.CompositionMode_Difference)
self.assertTrue(s.paintEffect())
self.assertEqual(s.paintEffect().blurLevel(), 10)
self.assertEqual(s.paintEffect().blurLevel(), 2.0)
def createBackgroundSettings(self):
s = QgsTextBackgroundSettings()
@ -83,7 +83,7 @@ class PyQgsTextFormatWidget(unittest.TestCase):
s.setStrokeWidth(7)
s.setStrokeWidthUnit(QgsUnitTypes.RenderMapUnits)
s.setStrokeWidthMapUnitScale(QgsMapUnitScale(QgsMapUnitScale(25, 26)))
s.setPaintEffect(QgsBlurEffect.create({'blur_level': '6', 'enabled': '1'}))
s.setPaintEffect(QgsBlurEffect.create({'blur_level': '6.0', 'blur_unit': QgsUnitTypes.encodeUnit(QgsUnitTypes.RenderMillimeters), 'enabled': '1'}))
return s
def checkBackgroundSettings(self, s):
@ -112,7 +112,7 @@ class PyQgsTextFormatWidget(unittest.TestCase):
self.assertEqual(s.strokeWidthUnit(), QgsUnitTypes.RenderMapUnits)
self.assertEqual(s.strokeWidthMapUnitScale(), QgsMapUnitScale(25, 26))
self.assertTrue(s.paintEffect())
self.assertEqual(s.paintEffect().blurLevel(), 6)
self.assertEqual(s.paintEffect().blurLevel(), 6.0)
def createShadowSettings(self):
s = QgsTextShadowSettings()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB