Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FEATURE] Allow setting paint effects on label background shapes
Can also be useful for improving text readability through
outer glows and blurs
  • Loading branch information
nyalldawson committed Apr 28, 2017
1 parent b9f102c commit debe109
Show file tree
Hide file tree
Showing 8 changed files with 495 additions and 378 deletions.
3 changes: 3 additions & 0 deletions python/core/qgstextrenderer.sip
Expand Up @@ -538,6 +538,9 @@ class QgsTextBackgroundSettings
*/
void readFromLayer( QgsVectorLayer* layer );

QgsPaintEffect* paintEffect() const;
void setPaintEffect( QgsPaintEffect* effect /Transfer/ );

/** Writes settings to a layer's custom properties.
* @param layer target vector layer
* @see readFromLayer()
Expand Down
55 changes: 55 additions & 0 deletions src/core/qgstextrenderer.cpp
Expand Up @@ -629,6 +629,17 @@ void QgsTextBackgroundSettings::setJoinStyle( Qt::PenJoinStyle style )
d->joinStyle = style;
}

QgsPaintEffect *QgsTextBackgroundSettings::paintEffect() const
{
return d->paintEffect;
}

void QgsTextBackgroundSettings::setPaintEffect( QgsPaintEffect *effect )
{
delete d->paintEffect;
d->paintEffect = effect;
}

void QgsTextBackgroundSettings::readFromLayer( QgsVectorLayer *layer )
{
d->enabled = layer->customProperty( QStringLiteral( "labeling/shapeDraw" ), QVariant( false ) ).toBool();
Expand Down Expand Up @@ -737,6 +748,16 @@ void QgsTextBackgroundSettings::readFromLayer( QgsVectorLayer *layer )
}
d->blendMode = QgsPainting::getCompositionMode(
static_cast< QgsPainting::BlendMode >( layer->customProperty( QStringLiteral( "labeling/shapeBlendMode" ), QVariant( QgsPainting::BlendNormal ) ).toUInt() ) );

if ( layer->customProperty( QStringLiteral( "labeling/shapeEffect" ) ).isValid() )
{
QDomDocument doc( QStringLiteral( "effect" ) );
doc.setContent( layer->customProperty( QStringLiteral( "labeling/shapeEffect" ) ).toString() );
QDomElement effectElem = doc.firstChildElement( QStringLiteral( "effect" ) ).firstChildElement( QStringLiteral( "effect" ) );
setPaintEffect( QgsApplication::paintEffectRegistry()->createEffect( effectElem ) );
}
else
setPaintEffect( nullptr );
}

void QgsTextBackgroundSettings::writeToLayer( QgsVectorLayer *layer ) const
Expand Down Expand Up @@ -767,6 +788,21 @@ void QgsTextBackgroundSettings::writeToLayer( QgsVectorLayer *layer ) const
layer->setCustomProperty( QStringLiteral( "labeling/shapeJoinStyle" ), static_cast< unsigned int >( d->joinStyle ) );
layer->setCustomProperty( QStringLiteral( "labeling/shapeOpacity" ), d->opacity );
layer->setCustomProperty( QStringLiteral( "labeling/shapeBlendMode" ), QgsPainting::getBlendModeEnum( d->blendMode ) );

if ( d->paintEffect && !QgsPaintEffectRegistry::isDefaultStack( d->paintEffect ) )
{
QDomDocument doc( QStringLiteral( "effect" ) );
QDomElement effectElem = doc.createElement( QStringLiteral( "effect" ) );
d->paintEffect->saveProperties( doc, effectElem );
QString effectProps;
QTextStream stream( &effectProps );
effectElem.save( stream, -1 );
layer->setCustomProperty( QStringLiteral( "labeling/shapeEffect" ), effectProps );
}
else
{
layer->removeCustomProperty( QStringLiteral( "labeling/shapeEffect" ) );
}
}

void QgsTextBackgroundSettings::readXml( const QDomElement &elem )
Expand Down Expand Up @@ -879,6 +915,11 @@ void QgsTextBackgroundSettings::readXml( const QDomElement &elem )
d->blendMode = QgsPainting::getCompositionMode(
static_cast< QgsPainting::BlendMode >( backgroundElem.attribute( QStringLiteral( "shapeBlendMode" ), QString::number( QgsPainting::BlendNormal ) ).toUInt() ) );

QDomElement effectElem = backgroundElem.firstChildElement( QStringLiteral( "effect" ) );
if ( !effectElem.isNull() )
setPaintEffect( QgsApplication::paintEffectRegistry()->createEffect( effectElem ) );
else
setPaintEffect( nullptr );
}

QDomElement QgsTextBackgroundSettings::writeXml( QDomDocument &doc ) const
Expand Down Expand Up @@ -910,6 +951,8 @@ QDomElement QgsTextBackgroundSettings::writeXml( QDomDocument &doc ) const
backgroundElem.setAttribute( QStringLiteral( "shapeJoinStyle" ), static_cast< unsigned int >( d->joinStyle ) );
backgroundElem.setAttribute( QStringLiteral( "shapeOpacity" ), d->opacity );
backgroundElem.setAttribute( QStringLiteral( "shapeBlendMode" ), QgsPainting::getBlendModeEnum( d->blendMode ) );
if ( d->paintEffect && !QgsPaintEffectRegistry::isDefaultStack( d->paintEffect ) )
d->paintEffect->saveProperties( doc, backgroundElem );
return backgroundElem;
}

Expand Down Expand Up @@ -1952,7 +1995,14 @@ void QgsTextRenderer::drawBackground( QgsRenderContext &context, QgsTextRenderer
{
QgsTextBackgroundSettings background = format.background();

QPainter *prevP = context.painter();
QPainter *p = context.painter();
if ( background.paintEffect() && background.paintEffect()->enabled() )
{
background.paintEffect()->begin( context );
p = context.painter();
}

//QgsDebugMsgLevel( QString( "Background label rotation: %1" ).arg( component.rotation() ), 4 );

// shared calculations between shapes and SVG
Expand Down Expand Up @@ -2289,6 +2339,11 @@ void QgsTextRenderer::drawBackground( QgsRenderContext &context, QgsTextRenderer
p->drawPicture( 0, 0, shapePict );
p->restore();
}
if ( background.paintEffect() && background.paintEffect()->enabled() )
{
background.paintEffect()->end( context );
context.setPainter( prevP );
}
}

void QgsTextRenderer::drawShadow( QgsRenderContext &context, const QgsTextRenderer::Component &component, const QgsTextFormat &format )
Expand Down
12 changes: 12 additions & 0 deletions src/core/qgstextrenderer.h
Expand Up @@ -577,6 +577,18 @@ class CORE_EXPORT QgsTextBackgroundSettings
*/
void setJoinStyle( Qt::PenJoinStyle style );

/** Returns the current paint effect for the background shape.
* \returns paint effect
* \see setPaintEffect()
*/
QgsPaintEffect *paintEffect() const;

/** Sets the current paint \a effect for the background shape.
* \param effect paint effect. Ownership is transferred to the background settings.
* \see paintEffect()
*/
void setPaintEffect( QgsPaintEffect *effect );

/** Reads settings from a layer's custom properties.
* \param layer source vector layer
* \see writeToLayer()
Expand Down
8 changes: 8 additions & 0 deletions src/core/qgstextrenderer_p.h
Expand Up @@ -111,6 +111,7 @@ class CORE_EXPORT QgsTextBackgroundSettingsPrivate : public QSharedData
, strokeWidth( 0.0 )
, strokeWidthUnits( QgsUnitTypes::RenderMillimeters )
, joinStyle( Qt::BevelJoin )
, paintEffect( nullptr )
{
}

Expand Down Expand Up @@ -139,9 +140,15 @@ class CORE_EXPORT QgsTextBackgroundSettingsPrivate : public QSharedData
, strokeWidthUnits( other.strokeWidthUnits )
, strokeWidthMapUnitScale( other.strokeWidthMapUnitScale )
, joinStyle( other.joinStyle )
, paintEffect( other.paintEffect ? other.paintEffect->clone() : nullptr )
{
}

~QgsTextBackgroundSettingsPrivate()
{
delete paintEffect;
}

bool enabled;
QgsTextBackgroundSettings::ShapeType type;
QString svgFile;
Expand All @@ -165,6 +172,7 @@ class CORE_EXPORT QgsTextBackgroundSettingsPrivate : public QSharedData
QgsUnitTypes::RenderUnit strokeWidthUnits;
QgsMapUnitScale strokeWidthMapUnitScale;
Qt::PenJoinStyle joinStyle;
QgsPaintEffect *paintEffect;
};


Expand Down
16 changes: 16 additions & 0 deletions src/gui/qgstextformatwidget.cpp
Expand Up @@ -264,6 +264,9 @@ void QgsTextFormatWidget::initWidget()
mBufferEffect.reset( QgsPaintEffectRegistry::defaultStack() );
connect( mBufferEffectWidget, &QgsEffectStackCompactWidget::changed, this, &QgsTextFormatWidget::updatePreview );
mBufferEffectWidget->setPaintEffect( mBufferEffect.get() );
mBackgroundEffect.reset( QgsPaintEffectRegistry::defaultStack() );
connect( mBackgroundEffectWidget, &QgsEffectStackCompactWidget::changed, this, &QgsTextFormatWidget::updatePreview );
mBackgroundEffectWidget->setPaintEffect( mBackgroundEffect.get() );

setDockMode( false );

Expand Down Expand Up @@ -695,6 +698,15 @@ void QgsTextFormatWidget::updateWidgetForFormat( const QgsTextFormat &format )
mLoadSvgParams = false;
on_mShapeTypeCmbBx_currentIndexChanged( background.type() ); // force update of shape background gui

if ( background.paintEffect() )
mBackgroundEffect.reset( background.paintEffect()->clone() );
else
{
mBackgroundEffect.reset( QgsPaintEffectRegistry::defaultStack() );
mBackgroundEffect->setEnabled( false );
}
mBackgroundEffectWidget->setPaintEffect( mBackgroundEffect.get() );

// drop shadow
mShadowDrawChkBx->setChecked( shadow.enabled() );
mShadowUnderCmbBx->setCurrentIndex( shadow.shadowPlacement() );
Expand Down Expand Up @@ -780,6 +792,10 @@ QgsTextFormat QgsTextFormatWidget::format() const
background.setJoinStyle( mShapePenStyleCmbBx->penJoinStyle() );
background.setOpacity( 1.0 - mShapeTranspSpinBox->value() / 100.0 );
background.setBlendMode( mShapeBlendCmbBx->blendMode() );
if ( mBackgroundEffect && !QgsPaintEffectRegistry::isDefaultStack( mBackgroundEffect.get() ) )
background.setPaintEffect( mBackgroundEffect->clone() );
else
background.setPaintEffect( nullptr );
format.setBackground( background );

// drop shadow
Expand Down
1 change: 1 addition & 0 deletions src/gui/qgstextformatwidget.h
Expand Up @@ -137,6 +137,7 @@ class GUI_EXPORT QgsTextFormatWidget : public QWidget, protected Ui::QgsTextForm
QgsMapCanvas *mMapCanvas = nullptr;
QgsCharacterSelectorDialog *mCharDlg = nullptr;
std::unique_ptr< QgsPaintEffect > mBufferEffect;
std::unique_ptr< QgsPaintEffect > mBackgroundEffect;

QFontDatabase mFontDB;

Expand Down

0 comments on commit debe109

Please sign in to comment.