QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgsgloweffect.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsgloweffect.cpp
3  -----------------
4  begin : December 2014
5  copyright : (C) 2014 Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgsgloweffect.h"
19 #include "qgssymbollayerutils.h"
20 #include "qgsimageoperation.h"
21 #include "qgscolorrampimpl.h"
22 #include "qgsunittypes.h"
23 
25  : mColor( Qt::white )
26 {
27 
28 }
29 
31  : QgsPaintEffect( other )
32 {
33  operator=( other );
34 }
35 
37 {
38  delete mRamp;
39 }
40 
42 {
43  if ( !source() || !enabled() || !context.painter() )
44  return;
45 
46  QImage im = sourceAsImage( context )->copy();
47 
48  QgsColorRamp *ramp = nullptr;
49  std::unique_ptr< QgsGradientColorRamp > tempRamp;
50  if ( mColorType == ColorRamp && mRamp )
51  {
52  ramp = mRamp;
53  }
54  else
55  {
56  //create a temporary ramp
57  QColor transparentColor = mColor;
58  transparentColor.setAlpha( 0 );
59  tempRamp.reset( new QgsGradientColorRamp( mColor, transparentColor ) );
60  ramp = tempRamp.get();
61  }
62 
65  dtProps.useMaxDistance = false;
66  dtProps.shadeExterior = shadeExterior();
67  dtProps.ramp = ramp;
68  QgsImageOperation::distanceTransform( im, dtProps, context.feedback() );
69 
70  if ( context.feedback() && context.feedback()->isCanceled() )
71  return;
72 
74  if ( blurLevel <= 16 )
75  {
76  QgsImageOperation::stackBlur( im, blurLevel, false, context.feedback() );
77  }
78  else
79  {
80  QImage *imb = QgsImageOperation::gaussianBlur( im, blurLevel, context.feedback() );
81  if ( !imb->isNull() )
82  im = QImage( *imb );
83  delete imb;
84  }
85 
86  if ( context.feedback() && context.feedback()->isCanceled() )
87  return;
88 
90 
91  if ( context.feedback() && context.feedback()->isCanceled() )
92  return;
93 
94  if ( !shadeExterior() )
95  {
96  //only keep interior portion
97  QPainter p( &im );
98  p.setRenderHint( QPainter::Antialiasing );
99  p.setCompositionMode( QPainter::CompositionMode_DestinationIn );
100  p.drawImage( 0, 0, *sourceAsImage( context ) );
101  p.end();
102  }
103 
104  QPainter *painter = context.painter();
105  const QgsScopedQPainterState painterState( painter );
106  painter->setCompositionMode( mBlendMode );
107  painter->drawImage( imageOffset( context ), im );
108 }
109 
110 QVariantMap QgsGlowEffect::properties() const
111 {
112  QVariantMap props;
113  props.insert( QStringLiteral( "enabled" ), mEnabled ? "1" : "0" );
114  props.insert( QStringLiteral( "draw_mode" ), QString::number( int( mDrawMode ) ) );
115  props.insert( QStringLiteral( "blend_mode" ), QString::number( int( mBlendMode ) ) );
116  props.insert( QStringLiteral( "opacity" ), QString::number( mOpacity ) );
117  props.insert( QStringLiteral( "blur_level" ), QString::number( mBlurLevel ) );
118  props.insert( QStringLiteral( "blur_unit" ), QgsUnitTypes::encodeUnit( mBlurUnit ) );
119  props.insert( QStringLiteral( "blur_unit_scale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mBlurMapUnitScale ) );
120  props.insert( QStringLiteral( "spread" ), QString::number( mSpread ) );
121  props.insert( QStringLiteral( "spread_unit" ), QgsUnitTypes::encodeUnit( mSpreadUnit ) );
122  props.insert( QStringLiteral( "spread_unit_scale" ), QgsSymbolLayerUtils::encodeMapUnitScale( mSpreadMapUnitScale ) );
123  props.insert( QStringLiteral( "color_type" ), QString::number( static_cast< int >( mColorType ) ) );
124  props.insert( QStringLiteral( "single_color" ), QgsSymbolLayerUtils::encodeColor( mColor ) );
125 
126  if ( mRamp )
127  {
128 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
129  props.unite( mRamp->properties() );
130 #else
131  props.insert( mRamp->properties() );
132 #endif
133  }
134 
135  return props;
136 }
137 
138 void QgsGlowEffect::readProperties( const QVariantMap &props )
139 {
140  bool ok;
141  const QPainter::CompositionMode mode = static_cast< QPainter::CompositionMode >( props.value( QStringLiteral( "blend_mode" ) ).toInt( &ok ) );
142  if ( ok )
143  {
144  mBlendMode = mode;
145  }
146  if ( props.contains( QStringLiteral( "transparency" ) ) )
147  {
148  const double transparency = props.value( QStringLiteral( "transparency" ) ).toDouble( &ok );
149  if ( ok )
150  {
151  mOpacity = 1.0 - transparency;
152  }
153  }
154  else
155  {
156  const double opacity = props.value( QStringLiteral( "opacity" ) ).toDouble( &ok );
157  if ( ok )
158  {
159  mOpacity = opacity;
160  }
161  }
162  mEnabled = props.value( QStringLiteral( "enabled" ), QStringLiteral( "1" ) ).toInt();
163  mDrawMode = static_cast< QgsPaintEffect::DrawMode >( props.value( QStringLiteral( "draw_mode" ), QStringLiteral( "2" ) ).toInt() );
164  const double level = props.value( QStringLiteral( "blur_level" ) ).toDouble( &ok );
165  if ( ok )
166  {
167  mBlurLevel = level;
168  if ( !props.contains( QStringLiteral( "blur_unit" ) ) )
169  {
170  // deal with pre blur unit era by assuming 96 dpi and converting pixel values as millimeters
171  mBlurLevel *= 0.2645;
172  }
173  }
174  mBlurUnit = QgsUnitTypes::decodeRenderUnit( props.value( QStringLiteral( "blur_unit" ) ).toString() );
175  mBlurMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( props.value( QStringLiteral( "blur_unit_scale" ) ).toString() );
176  const double spread = props.value( QStringLiteral( "spread" ) ).toDouble( &ok );
177  if ( ok )
178  {
179  mSpread = spread;
180  }
181  mSpreadUnit = QgsUnitTypes::decodeRenderUnit( props.value( QStringLiteral( "spread_unit" ) ).toString() );
182  mSpreadMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( props.value( QStringLiteral( "spread_unit_scale" ) ).toString() );
183  const QgsGlowEffect::GlowColorType type = static_cast< QgsGlowEffect::GlowColorType >( props.value( QStringLiteral( "color_type" ) ).toInt( &ok ) );
184  if ( ok )
185  {
186  mColorType = type;
187  }
188  if ( props.contains( QStringLiteral( "single_color" ) ) )
189  {
190  mColor = QgsSymbolLayerUtils::decodeColor( props.value( QStringLiteral( "single_color" ) ).toString() );
191  }
192 
193  //attempt to create color ramp from props
194  delete mRamp;
195  if ( props.contains( QStringLiteral( "rampType" ) ) && props[QStringLiteral( "rampType" )] == QgsCptCityColorRamp::typeString() )
196  {
198  }
199  else
200  {
202  }
203 }
204 
206 {
207  delete mRamp;
208  mRamp = ramp;
209 }
210 
212 {
213  if ( &rhs == this )
214  return *this;
215 
216  delete mRamp;
217 
218  mSpread = rhs.spread();
219  mSpreadUnit = rhs.spreadUnit();
221  mRamp = rhs.ramp() ? rhs.ramp()->clone() : nullptr;
222  mBlurLevel = rhs.blurLevel();
223  mBlurUnit = rhs.mBlurUnit;
225  mOpacity = rhs.opacity();
226  mColor = rhs.color();
227  mBlendMode = rhs.blendMode();
228  mColorType = rhs.colorType();
229 
230  return *this;
231 }
232 
233 QRectF QgsGlowEffect::boundingRect( const QRectF &rect, const QgsRenderContext &context ) const
234 {
235  //blur radius and spread size
238 
239  //plus possible extension due to blur, with a couple of extra pixels thrown in for safety
240  spread += blurLevel * 2 + 10;
241  return rect.adjusted( -spread, -spread, spread, spread );
242 }
243 
244 
245 //
246 // QgsOuterGlowEffect
247 //
248 
250  : QgsGlowEffect()
251 {
252 
253 }
254 
255 QgsPaintEffect *QgsOuterGlowEffect::create( const QVariantMap &map )
256 {
257  QgsOuterGlowEffect *effect = new QgsOuterGlowEffect();
258  effect->readProperties( map );
259  return effect;
260 }
261 
263 {
264  QgsOuterGlowEffect *newEffect = new QgsOuterGlowEffect( *this );
265  return newEffect;
266 }
267 
268 
269 //
270 // QgsInnerGlowEffect
271 //
272 
274  : QgsGlowEffect()
275 {
276 
277 }
278 
279 QgsPaintEffect *QgsInnerGlowEffect::create( const QVariantMap &map )
280 {
281  QgsInnerGlowEffect *effect = new QgsInnerGlowEffect();
282  effect->readProperties( map );
283  return effect;
284 }
285 
287 {
288  QgsInnerGlowEffect *newEffect = new QgsInnerGlowEffect( *this );
289  return newEffect;
290 }
QgsColorRamp
Abstract base class for color ramps.
Definition: qgscolorramp.h:29
QgsPaintEffect::DrawMode
DrawMode
Drawing modes for effects.
Definition: qgspainteffect.h:103
qgscolorrampimpl.h
QgsGlowEffect::blendMode
QPainter::CompositionMode blendMode() const
Returns the blend mode for the effect.
Definition: qgsgloweffect.h:239
QgsOuterGlowEffect::create
static QgsPaintEffect * create(const QVariantMap &map)
Creates a new QgsOuterGlowEffect effect from a properties string map.
Definition: qgsgloweffect.cpp:255
QgsGlowEffect::mSpread
double mSpread
Definition: qgsgloweffect.h:277
QgsGlowEffect::mSpreadUnit
QgsUnitTypes::RenderUnit mSpreadUnit
Definition: qgsgloweffect.h:278
QgsSymbolLayerUtils::encodeColor
static QString encodeColor(const QColor &color)
Definition: qgssymbollayerutils.cpp:64
QgsImageOperation::DistanceTransformProperties::ramp
QgsColorRamp * ramp
Color ramp to use for shading the distance transform.
Definition: qgsimageoperation.h:147
QgsGradientColorRamp
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
Definition: qgscolorrampimpl.h:136
QgsGlowEffect::mBlurMapUnitScale
QgsMapUnitScale mBlurMapUnitScale
Definition: qgsgloweffect.h:283
QgsSymbolLayerUtils::encodeMapUnitScale
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
Definition: qgssymbollayerutils.cpp:666
QgsGlowEffect::operator=
QgsGlowEffect & operator=(const QgsGlowEffect &rhs)
Definition: qgsgloweffect.cpp:211
QgsGlowEffect::color
QColor color() const
Returns the color for the glow.
Definition: qgsgloweffect.h:205
QgsGlowEffect::mBlurUnit
QgsUnitTypes::RenderUnit mBlurUnit
Definition: qgsgloweffect.h:282
QgsGlowEffect::setRamp
void setRamp(QgsColorRamp *ramp)
Sets the color ramp for the glow.
Definition: qgsgloweffect.cpp:205
qgssymbollayerutils.h
QgsFeedback::isCanceled
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:67
QgsRenderContext
Contains information about the context of a rendering operation.
Definition: qgsrendercontext.h:59
QgsImageOperation::DistanceTransformProperties::useMaxDistance
bool useMaxDistance
Set to true to automatically calculate the maximum distance in the transform to use as the spread val...
Definition: qgsimageoperation.h:136
qgsunittypes.h
QgsGlowEffect::QgsGlowEffect
QgsGlowEffect()
Definition: qgsgloweffect.cpp:24
qgsimageoperation.h
QgsSymbolLayerUtils::decodeColor
static QColor decodeColor(const QString &str)
Definition: qgssymbollayerutils.cpp:69
QgsGlowEffect::properties
QVariantMap properties() const override
Returns the properties describing the paint effect encoded in a string format.
Definition: qgsgloweffect.cpp:110
QgsGlowEffect::mColorType
GlowColorType mColorType
Definition: qgsgloweffect.h:287
QgsImageOperation::gaussianBlur
static QImage * gaussianBlur(QImage &image, int radius, QgsFeedback *feedback=nullptr)
Performs a gaussian blur on an image.
Definition: qgsimageoperation.cpp:651
QgsPaintEffect::mEnabled
bool mEnabled
Definition: qgspainteffect.h:224
QgsGlowEffect::shadeExterior
virtual bool shadeExterior() const =0
Specifies whether the glow is drawn outside the picture or within the picture.
QgsUnitTypes::decodeRenderUnit
static Q_INVOKABLE QgsUnitTypes::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
Definition: qgsunittypes.cpp:2948
QgsCptCityColorRamp::typeString
static QString typeString()
Returns the string identifier for QgsCptCityColorRamp.
Definition: qgscolorrampimpl.h:750
QgsInnerGlowEffect::create
static QgsPaintEffect * create(const QVariantMap &map)
Creates a new QgsInnerGlowEffect effect from a properties string map.
Definition: qgsgloweffect.cpp:279
QgsUnitTypes::encodeUnit
static Q_INVOKABLE QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
Definition: qgsunittypes.cpp:122
QgsGlowEffect
Base class for paint effect which draw a glow inside or outside a picture.
Definition: qgsgloweffect.h:39
QgsGradientColorRamp::create
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsColorRamp from a map of properties.
Definition: qgscolorrampimpl.cpp:216
QgsGlowEffect::spreadMapUnitScale
const QgsMapUnitScale & spreadMapUnitScale() const
Returns the map unit scale used for the spread distance.
Definition: qgsgloweffect.h:110
QgsGlowEffect::boundingRect
QRectF boundingRect(const QRectF &rect, const QgsRenderContext &context) const override
Returns the bounding rect required for drawing the effect.
Definition: qgsgloweffect.cpp:233
QgsGlowEffect::ColorRamp
@ ColorRamp
Use colors from a color ramp.
Definition: qgsgloweffect.h:48
QgsOuterGlowEffect::QgsOuterGlowEffect
QgsOuterGlowEffect()
Definition: qgsgloweffect.cpp:249
QgsColorRamp::properties
virtual QVariantMap properties() const =0
Returns a string map containing all the color ramp's properties.
qgsgloweffect.h
QgsGlowEffect::blurLevel
double blurLevel() const
Returns the blur level (radius) for the glow.
Definition: qgsgloweffect.h:129
QgsGlowEffect::mRamp
QgsColorRamp * mRamp
Definition: qgsgloweffect.h:280
QgsScopedQPainterState
Scoped object for saving and restoring a QPainter object's state.
Definition: qgsrendercontext.h:1336
QgsCptCityColorRamp::create
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates the symbol layer.
Definition: qgscolorrampimpl.cpp:944
QgsPaintEffect::imageOffset
QPointF imageOffset(const QgsRenderContext &context) const
Returns the offset which should be used when drawing the source image on to a destination render cont...
Definition: qgspainteffect.cpp:170
QgsGlowEffect::ramp
QgsColorRamp * ramp() const
Returns the color ramp used for the glow.
Definition: qgsgloweffect.h:223
QgsInnerGlowEffect::QgsInnerGlowEffect
QgsInnerGlowEffect()
Definition: qgsgloweffect.cpp:273
QgsInnerGlowEffect
A paint effect which draws a glow within a picture.
Definition: qgsgloweffect.h:332
QgsColorRamp::clone
virtual QgsColorRamp * clone() const =0
Creates a clone of the color ramp.
QgsRenderContext::convertToPainterUnits
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
Definition: qgsrendercontext.cpp:367
QgsImageOperation::DistanceTransformProperties::shadeExterior
bool shadeExterior
Set to true to perform the distance transform on transparent pixels in the source image,...
Definition: qgsimageoperation.h:130
QgsPaintEffect::mDrawMode
DrawMode mDrawMode
Definition: qgspainteffect.h:225
QgsGlowEffect::mBlendMode
QPainter::CompositionMode mBlendMode
Definition: qgsgloweffect.h:286
QgsGlowEffect::readProperties
void readProperties(const QVariantMap &props) override
Reads a string map of an effect's properties and restores the effect to the state described by the pr...
Definition: qgsgloweffect.cpp:138
QgsGlowEffect::mColor
QColor mColor
Definition: qgsgloweffect.h:285
QgsRenderContext::feedback
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly during rendering to check if rendering shou...
Definition: qgsrendercontext.cpp:206
QgsGlowEffect::~QgsGlowEffect
~QgsGlowEffect() override
Definition: qgsgloweffect.cpp:36
QgsPaintEffect::sourceAsImage
QImage * sourceAsImage(QgsRenderContext &context)
Returns the source QPicture rendered to a new QImage.
Definition: qgspainteffect.cpp:145
QgsGlowEffect::colorType
GlowColorType colorType() const
Returns the color mode used for the glow.
Definition: qgsgloweffect.h:260
QgsPaintEffect::source
const QPicture * source() const
Returns the source QPicture.
Definition: qgspainteffect.h:253
QgsImageOperation::DistanceTransformProperties::spread
double spread
Maximum distance (in pixels) for the distance transform shading to spread.
Definition: qgsimageoperation.h:142
QgsPaintEffect
Base class for visual effects which can be applied to QPicture drawings.
Definition: qgspainteffect.h:52
QgsOuterGlowEffect
A paint effect which draws a glow outside of a picture.
Definition: qgsgloweffect.h:300
QgsImageOperation::DistanceTransformProperties
Struct for storing properties of a distance transform operation.
Definition: qgsimageoperation.h:122
QgsGlowEffect::opacity
double opacity() const
Returns the opacity for the effect.
Definition: qgsgloweffect.h:185
QgsGlowEffect::mSpreadMapUnitScale
QgsMapUnitScale mSpreadMapUnitScale
Definition: qgsgloweffect.h:279
QgsImageOperation::multiplyOpacity
static void multiplyOpacity(QImage &image, double factor, QgsFeedback *feedback=nullptr)
Multiplies opacity of image pixel values by a factor.
Definition: qgsimageoperation.cpp:335
QgsImageOperation::stackBlur
static void stackBlur(QImage &image, int radius, bool alphaOnly=false, QgsFeedback *feedback=nullptr)
Performs a stack blur on an image.
Definition: qgsimageoperation.cpp:585
QgsOuterGlowEffect::clone
QgsOuterGlowEffect * clone() const override
Duplicates an effect by creating a deep copy of the effect.
Definition: qgsgloweffect.cpp:262
QgsGlowEffect::GlowColorType
GlowColorType
Color sources for the glow.
Definition: qgsgloweffect.h:45
QgsGlowEffect::mOpacity
double mOpacity
Definition: qgsgloweffect.h:284
QgsRenderContext::painter
QPainter * painter()
Returns the destination QPainter for the render operation.
Definition: qgsrendercontext.h:112
QgsPaintEffect::enabled
bool enabled() const
Returns whether the effect is enabled.
Definition: qgspainteffect.h:197
QgsPaintEffect::type
virtual QString type() const =0
Returns the effect type.
Qgis::RenderSubcomponentProperty::GlowSpread
@ GlowSpread
Glow spread size.
Qgis::RenderSubcomponentProperty::BlurSize
@ BlurSize
Blur size.
QgsSymbolLayerUtils::decodeMapUnitScale
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
Definition: qgssymbollayerutils.cpp:676
QgsInnerGlowEffect::clone
QgsInnerGlowEffect * clone() const override
Duplicates an effect by creating a deep copy of the effect.
Definition: qgsgloweffect.cpp:286
QgsGlowEffect::spread
double spread() const
Returns the spread distance used for drawing the glow effect.
Definition: qgsgloweffect.h:74
QgsGlowEffect::spreadUnit
QgsUnitTypes::RenderUnit spreadUnit() const
Returns the units used for the glow spread distance.
Definition: qgsgloweffect.h:92
QgsGlowEffect::mBlurLevel
double mBlurLevel
Definition: qgsgloweffect.h:281
QgsGlowEffect::draw
void draw(QgsRenderContext &context) override
Handles drawing of the effect's result on to the specified render context.
Definition: qgsgloweffect.cpp:41
QgsImageOperation::distanceTransform
static void distanceTransform(QImage &image, const QgsImageOperation::DistanceTransformProperties &properties, QgsFeedback *feedback=nullptr)
Performs a distance transform on the source image and shades the result using a color ramp.
Definition: qgsimageoperation.cpp:387