Skip to content

Commit debe109

Browse files
committed
[FEATURE] Allow setting paint effects on label background shapes
Can also be useful for improving text readability through outer glows and blurs
1 parent b9f102c commit debe109

8 files changed

+495
-378
lines changed

python/core/qgstextrenderer.sip

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,9 @@ class QgsTextBackgroundSettings
538538
*/
539539
void readFromLayer( QgsVectorLayer* layer );
540540

541+
QgsPaintEffect* paintEffect() const;
542+
void setPaintEffect( QgsPaintEffect* effect /Transfer/ );
543+
541544
/** Writes settings to a layer's custom properties.
542545
* @param layer target vector layer
543546
* @see readFromLayer()

src/core/qgstextrenderer.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,17 @@ void QgsTextBackgroundSettings::setJoinStyle( Qt::PenJoinStyle style )
629629
d->joinStyle = style;
630630
}
631631

632+
QgsPaintEffect *QgsTextBackgroundSettings::paintEffect() const
633+
{
634+
return d->paintEffect;
635+
}
636+
637+
void QgsTextBackgroundSettings::setPaintEffect( QgsPaintEffect *effect )
638+
{
639+
delete d->paintEffect;
640+
d->paintEffect = effect;
641+
}
642+
632643
void QgsTextBackgroundSettings::readFromLayer( QgsVectorLayer *layer )
633644
{
634645
d->enabled = layer->customProperty( QStringLiteral( "labeling/shapeDraw" ), QVariant( false ) ).toBool();
@@ -737,6 +748,16 @@ void QgsTextBackgroundSettings::readFromLayer( QgsVectorLayer *layer )
737748
}
738749
d->blendMode = QgsPainting::getCompositionMode(
739750
static_cast< QgsPainting::BlendMode >( layer->customProperty( QStringLiteral( "labeling/shapeBlendMode" ), QVariant( QgsPainting::BlendNormal ) ).toUInt() ) );
751+
752+
if ( layer->customProperty( QStringLiteral( "labeling/shapeEffect" ) ).isValid() )
753+
{
754+
QDomDocument doc( QStringLiteral( "effect" ) );
755+
doc.setContent( layer->customProperty( QStringLiteral( "labeling/shapeEffect" ) ).toString() );
756+
QDomElement effectElem = doc.firstChildElement( QStringLiteral( "effect" ) ).firstChildElement( QStringLiteral( "effect" ) );
757+
setPaintEffect( QgsApplication::paintEffectRegistry()->createEffect( effectElem ) );
758+
}
759+
else
760+
setPaintEffect( nullptr );
740761
}
741762

742763
void QgsTextBackgroundSettings::writeToLayer( QgsVectorLayer *layer ) const
@@ -767,6 +788,21 @@ void QgsTextBackgroundSettings::writeToLayer( QgsVectorLayer *layer ) const
767788
layer->setCustomProperty( QStringLiteral( "labeling/shapeJoinStyle" ), static_cast< unsigned int >( d->joinStyle ) );
768789
layer->setCustomProperty( QStringLiteral( "labeling/shapeOpacity" ), d->opacity );
769790
layer->setCustomProperty( QStringLiteral( "labeling/shapeBlendMode" ), QgsPainting::getBlendModeEnum( d->blendMode ) );
791+
792+
if ( d->paintEffect && !QgsPaintEffectRegistry::isDefaultStack( d->paintEffect ) )
793+
{
794+
QDomDocument doc( QStringLiteral( "effect" ) );
795+
QDomElement effectElem = doc.createElement( QStringLiteral( "effect" ) );
796+
d->paintEffect->saveProperties( doc, effectElem );
797+
QString effectProps;
798+
QTextStream stream( &effectProps );
799+
effectElem.save( stream, -1 );
800+
layer->setCustomProperty( QStringLiteral( "labeling/shapeEffect" ), effectProps );
801+
}
802+
else
803+
{
804+
layer->removeCustomProperty( QStringLiteral( "labeling/shapeEffect" ) );
805+
}
770806
}
771807

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

918+
QDomElement effectElem = backgroundElem.firstChildElement( QStringLiteral( "effect" ) );
919+
if ( !effectElem.isNull() )
920+
setPaintEffect( QgsApplication::paintEffectRegistry()->createEffect( effectElem ) );
921+
else
922+
setPaintEffect( nullptr );
882923
}
883924

884925
QDomElement QgsTextBackgroundSettings::writeXml( QDomDocument &doc ) const
@@ -910,6 +951,8 @@ QDomElement QgsTextBackgroundSettings::writeXml( QDomDocument &doc ) const
910951
backgroundElem.setAttribute( QStringLiteral( "shapeJoinStyle" ), static_cast< unsigned int >( d->joinStyle ) );
911952
backgroundElem.setAttribute( QStringLiteral( "shapeOpacity" ), d->opacity );
912953
backgroundElem.setAttribute( QStringLiteral( "shapeBlendMode" ), QgsPainting::getBlendModeEnum( d->blendMode ) );
954+
if ( d->paintEffect && !QgsPaintEffectRegistry::isDefaultStack( d->paintEffect ) )
955+
d->paintEffect->saveProperties( doc, backgroundElem );
913956
return backgroundElem;
914957
}
915958

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

1998+
QPainter *prevP = context.painter();
19551999
QPainter *p = context.painter();
2000+
if ( background.paintEffect() && background.paintEffect()->enabled() )
2001+
{
2002+
background.paintEffect()->begin( context );
2003+
p = context.painter();
2004+
}
2005+
19562006
//QgsDebugMsgLevel( QString( "Background label rotation: %1" ).arg( component.rotation() ), 4 );
19572007

19582008
// shared calculations between shapes and SVG
@@ -2289,6 +2339,11 @@ void QgsTextRenderer::drawBackground( QgsRenderContext &context, QgsTextRenderer
22892339
p->drawPicture( 0, 0, shapePict );
22902340
p->restore();
22912341
}
2342+
if ( background.paintEffect() && background.paintEffect()->enabled() )
2343+
{
2344+
background.paintEffect()->end( context );
2345+
context.setPainter( prevP );
2346+
}
22922347
}
22932348

22942349
void QgsTextRenderer::drawShadow( QgsRenderContext &context, const QgsTextRenderer::Component &component, const QgsTextFormat &format )

src/core/qgstextrenderer.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,18 @@ class CORE_EXPORT QgsTextBackgroundSettings
577577
*/
578578
void setJoinStyle( Qt::PenJoinStyle style );
579579

580+
/** Returns the current paint effect for the background shape.
581+
* \returns paint effect
582+
* \see setPaintEffect()
583+
*/
584+
QgsPaintEffect *paintEffect() const;
585+
586+
/** Sets the current paint \a effect for the background shape.
587+
* \param effect paint effect. Ownership is transferred to the background settings.
588+
* \see paintEffect()
589+
*/
590+
void setPaintEffect( QgsPaintEffect *effect );
591+
580592
/** Reads settings from a layer's custom properties.
581593
* \param layer source vector layer
582594
* \see writeToLayer()

src/core/qgstextrenderer_p.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ class CORE_EXPORT QgsTextBackgroundSettingsPrivate : public QSharedData
111111
, strokeWidth( 0.0 )
112112
, strokeWidthUnits( QgsUnitTypes::RenderMillimeters )
113113
, joinStyle( Qt::BevelJoin )
114+
, paintEffect( nullptr )
114115
{
115116
}
116117

@@ -139,9 +140,15 @@ class CORE_EXPORT QgsTextBackgroundSettingsPrivate : public QSharedData
139140
, strokeWidthUnits( other.strokeWidthUnits )
140141
, strokeWidthMapUnitScale( other.strokeWidthMapUnitScale )
141142
, joinStyle( other.joinStyle )
143+
, paintEffect( other.paintEffect ? other.paintEffect->clone() : nullptr )
142144
{
143145
}
144146

147+
~QgsTextBackgroundSettingsPrivate()
148+
{
149+
delete paintEffect;
150+
}
151+
145152
bool enabled;
146153
QgsTextBackgroundSettings::ShapeType type;
147154
QString svgFile;
@@ -165,6 +172,7 @@ class CORE_EXPORT QgsTextBackgroundSettingsPrivate : public QSharedData
165172
QgsUnitTypes::RenderUnit strokeWidthUnits;
166173
QgsMapUnitScale strokeWidthMapUnitScale;
167174
Qt::PenJoinStyle joinStyle;
175+
QgsPaintEffect *paintEffect;
168176
};
169177

170178

src/gui/qgstextformatwidget.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,9 @@ void QgsTextFormatWidget::initWidget()
264264
mBufferEffect.reset( QgsPaintEffectRegistry::defaultStack() );
265265
connect( mBufferEffectWidget, &QgsEffectStackCompactWidget::changed, this, &QgsTextFormatWidget::updatePreview );
266266
mBufferEffectWidget->setPaintEffect( mBufferEffect.get() );
267+
mBackgroundEffect.reset( QgsPaintEffectRegistry::defaultStack() );
268+
connect( mBackgroundEffectWidget, &QgsEffectStackCompactWidget::changed, this, &QgsTextFormatWidget::updatePreview );
269+
mBackgroundEffectWidget->setPaintEffect( mBackgroundEffect.get() );
267270

268271
setDockMode( false );
269272

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

701+
if ( background.paintEffect() )
702+
mBackgroundEffect.reset( background.paintEffect()->clone() );
703+
else
704+
{
705+
mBackgroundEffect.reset( QgsPaintEffectRegistry::defaultStack() );
706+
mBackgroundEffect->setEnabled( false );
707+
}
708+
mBackgroundEffectWidget->setPaintEffect( mBackgroundEffect.get() );
709+
698710
// drop shadow
699711
mShadowDrawChkBx->setChecked( shadow.enabled() );
700712
mShadowUnderCmbBx->setCurrentIndex( shadow.shadowPlacement() );
@@ -780,6 +792,10 @@ QgsTextFormat QgsTextFormatWidget::format() const
780792
background.setJoinStyle( mShapePenStyleCmbBx->penJoinStyle() );
781793
background.setOpacity( 1.0 - mShapeTranspSpinBox->value() / 100.0 );
782794
background.setBlendMode( mShapeBlendCmbBx->blendMode() );
795+
if ( mBackgroundEffect && !QgsPaintEffectRegistry::isDefaultStack( mBackgroundEffect.get() ) )
796+
background.setPaintEffect( mBackgroundEffect->clone() );
797+
else
798+
background.setPaintEffect( nullptr );
783799
format.setBackground( background );
784800

785801
// drop shadow

src/gui/qgstextformatwidget.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ class GUI_EXPORT QgsTextFormatWidget : public QWidget, protected Ui::QgsTextForm
137137
QgsMapCanvas *mMapCanvas = nullptr;
138138
QgsCharacterSelectorDialog *mCharDlg = nullptr;
139139
std::unique_ptr< QgsPaintEffect > mBufferEffect;
140+
std::unique_ptr< QgsPaintEffect > mBackgroundEffect;
140141

141142
QFontDatabase mFontDB;
142143

0 commit comments

Comments
 (0)