1 /***************************************************************************
2 qgstextmasksettings.cpp
3 -----------------
4 begin : May 2020
5 copyright : (C) Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16 #include "qgstextmasksettings.h"
17 #include "qgstextrenderer_p.h"
18 #include "qgspallabeling.h"
19 #include "qgssymbollayerutils.h"
20 #include "qgspainteffectregistry.h"
21
QgsTextMaskSettings()22 QgsTextMaskSettings::QgsTextMaskSettings()
23 {
24 d = new QgsTextMaskSettingsPrivate();
25 }
26
27 QgsTextMaskSettings::~QgsTextMaskSettings() = default;
28
QgsTextMaskSettings(const QgsTextMaskSettings & other)29 QgsTextMaskSettings::QgsTextMaskSettings( const QgsTextMaskSettings &other ) //NOLINT
30 : d( other.d )
31 {
32 }
33
operator =(const QgsTextMaskSettings & other)34 QgsTextMaskSettings &QgsTextMaskSettings::operator=( const QgsTextMaskSettings &other ) //NOLINT
35 {
36 d = other.d;
37 return *this;
38 }
39
operator ==(const QgsTextMaskSettings & other) const40 bool QgsTextMaskSettings::operator==( const QgsTextMaskSettings &other ) const
41 {
42 if ( d->enabled != other.enabled()
43 || d->type != other.type()
44 || d->size != other.size()
45 || d->sizeUnit != other.sizeUnit()
46 || d->sizeMapUnitScale != other.sizeMapUnitScale()
47 || d->joinStyle != other.joinStyle()
48 || d->opacity != other.opacity()
49 || d->maskedSymbolLayers != other.maskedSymbolLayers() )
50 return false;
51
52 if ( static_cast< bool >( d->paintEffect ) != static_cast< bool >( other.paintEffect() )
53 || ( d->paintEffect && d->paintEffect->properties() != other.paintEffect()->properties() ) )
54 return false;
55
56 return true;
57 }
58
operator !=(const QgsTextMaskSettings & other) const59 bool QgsTextMaskSettings::operator!=( const QgsTextMaskSettings &other ) const
60 {
61 return !( *this == other );
62 }
63
enabled() const64 bool QgsTextMaskSettings::enabled() const
65 {
66 return d->enabled;
67 }
68
setEnabled(bool enabled)69 void QgsTextMaskSettings::setEnabled( bool enabled )
70 {
71 d->enabled = enabled;
72 }
73
type() const74 QgsTextMaskSettings::MaskType QgsTextMaskSettings::type() const
75 {
76 return d->type;
77 }
78
setType(QgsTextMaskSettings::MaskType type)79 void QgsTextMaskSettings::setType( QgsTextMaskSettings::MaskType type )
80 {
81 d->type = type;
82 }
83
84
size() const85 double QgsTextMaskSettings::size() const
86 {
87 return d->size;
88 }
89
setSize(double size)90 void QgsTextMaskSettings::setSize( double size )
91 {
92 d->size = size;
93 }
94
sizeUnit() const95 QgsUnitTypes::RenderUnit QgsTextMaskSettings::sizeUnit() const
96 {
97 return d->sizeUnit;
98 }
99
setSizeUnit(QgsUnitTypes::RenderUnit unit)100 void QgsTextMaskSettings::setSizeUnit( QgsUnitTypes::RenderUnit unit )
101 {
102 d->sizeUnit = unit;
103 }
104
sizeMapUnitScale() const105 QgsMapUnitScale QgsTextMaskSettings::sizeMapUnitScale() const
106 {
107 return d->sizeMapUnitScale;
108 }
109
setSizeMapUnitScale(const QgsMapUnitScale & scale)110 void QgsTextMaskSettings::setSizeMapUnitScale( const QgsMapUnitScale &scale )
111 {
112 d->sizeMapUnitScale = scale;
113 }
114
joinStyle() const115 Qt::PenJoinStyle QgsTextMaskSettings::joinStyle() const
116 {
117 return d->joinStyle;
118 }
119
setJoinStyle(Qt::PenJoinStyle style)120 void QgsTextMaskSettings::setJoinStyle( Qt::PenJoinStyle style )
121 {
122 d->joinStyle = style;
123 }
124
opacity() const125 double QgsTextMaskSettings::opacity() const
126 {
127 return d->opacity;
128 }
129
setOpacity(double opacity)130 void QgsTextMaskSettings::setOpacity( double opacity )
131 {
132 d->opacity = opacity;
133 }
134
paintEffect() const135 QgsPaintEffect *QgsTextMaskSettings::paintEffect() const
136 {
137 return d->paintEffect.get();
138 }
139
setPaintEffect(QgsPaintEffect * effect)140 void QgsTextMaskSettings::setPaintEffect( QgsPaintEffect *effect )
141 {
142 d->paintEffect.reset( effect );
143 }
144
updateDataDefinedProperties(QgsRenderContext & context,const QgsPropertyCollection & properties)145 void QgsTextMaskSettings::updateDataDefinedProperties( QgsRenderContext &context, const QgsPropertyCollection &properties )
146 {
147 if ( properties.isActive( QgsPalLayerSettings::MaskEnabled ) )
148 {
149 context.expressionContext().setOriginalValueVariable( d->enabled );
150 d->enabled = properties.valueAsBool( QgsPalLayerSettings::MaskEnabled, context.expressionContext(), d->enabled );
151 }
152
153 if ( properties.isActive( QgsPalLayerSettings::MaskBufferSize ) )
154 {
155 context.expressionContext().setOriginalValueVariable( d->size );
156 d->size = properties.valueAsDouble( QgsPalLayerSettings::MaskBufferSize, context.expressionContext(), d->size );
157 }
158
159 if ( properties.isActive( QgsPalLayerSettings::MaskBufferUnit ) )
160 {
161 QVariant exprVal = properties.value( QgsPalLayerSettings::MaskBufferUnit, context.expressionContext() );
162 if ( !exprVal.isNull() )
163 {
164 QString units = exprVal.toString();
165 if ( !units.isEmpty() )
166 {
167 bool ok;
168 QgsUnitTypes::RenderUnit res = QgsUnitTypes::decodeRenderUnit( units, &ok );
169 if ( ok )
170 d->sizeUnit = res;
171 }
172 }
173 }
174
175 if ( properties.isActive( QgsPalLayerSettings::MaskOpacity ) )
176 {
177 context.expressionContext().setOriginalValueVariable( d->opacity * 100 );
178 const QVariant val = properties.value( QgsPalLayerSettings::MaskOpacity, context.expressionContext(), d->opacity * 100 );
179 if ( !val.isNull() )
180 {
181 d->opacity = val.toDouble() / 100.0;
182 }
183 }
184
185 if ( properties.isActive( QgsPalLayerSettings::MaskJoinStyle ) )
186 {
187 QVariant exprVal = properties.value( QgsPalLayerSettings::MaskJoinStyle, context.expressionContext() );
188 QString joinstr = exprVal.toString().trimmed();
189 if ( !joinstr.isEmpty() )
190 {
191 d->joinStyle = QgsSymbolLayerUtils::decodePenJoinStyle( joinstr );
192 }
193 }
194 }
195
referencedFields(const QgsRenderContext &) const196 QSet<QString> QgsTextMaskSettings::referencedFields( const QgsRenderContext & ) const
197 {
198 return QSet< QString >(); // nothing for now
199 }
200
readXml(const QDomElement & elem)201 void QgsTextMaskSettings::readXml( const QDomElement &elem )
202 {
203 QDomElement textMaskElem = elem.firstChildElement( QStringLiteral( "text-mask" ) );
204 d->enabled = textMaskElem.attribute( QStringLiteral( "maskEnabled" ), QStringLiteral( "0" ) ).toInt();
205 d->type = static_cast<QgsTextMaskSettings::MaskType>( textMaskElem.attribute( QStringLiteral( "maskType" ), QStringLiteral( "0" ) ).toInt() );
206 d->size = textMaskElem.attribute( QStringLiteral( "maskSize" ), QStringLiteral( "0" ) ).toDouble();
207 d->sizeUnit = QgsUnitTypes::decodeRenderUnit( textMaskElem.attribute( QStringLiteral( "maskSizeUnits" ) ) );
208 d->sizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( textMaskElem.attribute( QStringLiteral( "maskSizeMapUnitScale" ) ) );
209 d->joinStyle = static_cast< Qt::PenJoinStyle >( textMaskElem.attribute( QStringLiteral( "maskJoinStyle" ), QString::number( Qt::RoundJoin ) ).toUInt() );
210 d->opacity = textMaskElem.attribute( QStringLiteral( "maskOpacity" ), QStringLiteral( "1.0" ) ).toDouble();
211 QDomElement effectElem = textMaskElem.firstChildElement( QStringLiteral( "effect" ) );
212 if ( !effectElem.isNull() )
213 setPaintEffect( QgsApplication::paintEffectRegistry()->createEffect( effectElem ) );
214 else
215 setPaintEffect( nullptr );
216 d->maskedSymbolLayers = stringToSymbolLayerReferenceList( textMaskElem.attribute( QStringLiteral( "maskedSymbolLayers" ) ) );
217 }
218
writeXml(QDomDocument & doc) const219 QDomElement QgsTextMaskSettings::writeXml( QDomDocument &doc ) const
220 {
221 QDomElement textMaskElem = doc.createElement( QStringLiteral( "text-mask" ) );
222 textMaskElem.setAttribute( QStringLiteral( "maskEnabled" ), d->enabled );
223 textMaskElem.setAttribute( QStringLiteral( "maskType" ), d->type );
224 textMaskElem.setAttribute( QStringLiteral( "maskSize" ), d->size );
225 textMaskElem.setAttribute( QStringLiteral( "maskSizeUnits" ), QgsUnitTypes::encodeUnit( d->sizeUnit ) );
226 textMaskElem.setAttribute( QStringLiteral( "maskSizeMapUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( d->sizeMapUnitScale ) );
227 textMaskElem.setAttribute( QStringLiteral( "maskJoinStyle" ), static_cast< unsigned int >( d->joinStyle ) );
228 textMaskElem.setAttribute( QStringLiteral( "maskOpacity" ), d->opacity );
229 if ( d->paintEffect && !QgsPaintEffectRegistry::isDefaultStack( d->paintEffect.get() ) )
230 d->paintEffect->saveProperties( doc, textMaskElem );
231 textMaskElem.setAttribute( QStringLiteral( "maskedSymbolLayers" ), symbolLayerReferenceListToString( d->maskedSymbolLayers ) );
232 return textMaskElem;
233 }
234
maskedSymbolLayers() const235 QgsSymbolLayerReferenceList QgsTextMaskSettings::maskedSymbolLayers() const
236 {
237 return d->maskedSymbolLayers;
238 }
239
setMaskedSymbolLayers(QgsSymbolLayerReferenceList maskedSymbols)240 void QgsTextMaskSettings::setMaskedSymbolLayers( QgsSymbolLayerReferenceList maskedSymbols )
241 {
242 d->maskedSymbolLayers = maskedSymbols;
243 }
244