Skip to content

Commit

Permalink
[FEATURE] Allow setting paint effects on label background shapes
Browse files Browse the repository at this point in the history
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.