QGIS API Documentation  2.14.0-Essen
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 "qgssymbollayerv2utils.h"
20 #include "qgsimageoperation.h"
21 #include "qgsvectorcolorrampv2.h"
22 #include "qgsunittypes.h"
23 
25  : QgsPaintEffect()
26  , mSpread( 2.0 )
27  , mSpreadUnit( QgsSymbolV2::MM )
28  , mRamp( nullptr )
29  , mBlurLevel( 3 )
30  , mTransparency( 0.5 )
31  , mColor( Qt::white )
32  , mBlendMode( QPainter::CompositionMode_SourceOver )
33  , mColorType( SingleColor )
34 {
35 
36 }
37 
39  : QgsPaintEffect( other )
40  , mSpread( other.spread() )
41  , mSpreadUnit( other.spreadUnit() )
43  , mRamp( nullptr )
44  , mBlurLevel( other.blurLevel() )
45  , mTransparency( other.transparency() )
46  , mColor( other.color() )
47  , mBlendMode( other.blendMode() )
48  , mColorType( other.colorType() )
49 {
50  if ( other.ramp() )
51  {
52  mRamp = other.ramp()->clone();
53  }
54 }
55 
57 {
58  delete mRamp;
59 }
60 
62 {
63  if ( !source() || !enabled() || !context.painter() )
64  return;
65 
66  QImage im = sourceAsImage( context )->copy();
67 
68  QgsVectorColorRampV2* ramp = nullptr;
69  if ( mColorType == ColorRamp && mRamp )
70  {
71  ramp = mRamp;
72  }
73  else
74  {
75  //create a temporary ramp
76  QColor transparentColor = mColor;
77  transparentColor.setAlpha( 0 );
78  ramp = new QgsVectorGradientColorRampV2( mColor, transparentColor );
79  }
80 
83  dtProps.useMaxDistance = false;
84  dtProps.shadeExterior = shadeExterior();
85  dtProps.ramp = ramp;
87 
88  if ( mBlurLevel > 0 )
89  {
91  }
92 
94 
95  if ( !shadeExterior() )
96  {
97  //only keep interior portion
98  QPainter p( &im );
99  p.setRenderHint( QPainter::Antialiasing );
100  p.setCompositionMode( QPainter::CompositionMode_DestinationIn );
101  p.drawImage( 0, 0, *sourceAsImage( context ) );
102  p.end();
103  }
104 
105  QPainter* painter = context.painter();
106  painter->save();
107  painter->setCompositionMode( mBlendMode );
108  painter->drawImage( imageOffset( context ), im );
109  painter->restore();
110 
111  if ( !mRamp )
112  {
113  //delete temporary ramp
114  delete ramp;
115  }
116 }
117 
119 {
120  QgsStringMap props;
121  props.insert( "enabled", mEnabled ? "1" : "0" );
122  props.insert( "draw_mode", QString::number( int( mDrawMode ) ) );
123  props.insert( "blend_mode", QString::number( int( mBlendMode ) ) );
124  props.insert( "transparency", QString::number( mTransparency ) );
125  props.insert( "blur_level", QString::number( mBlurLevel ) );
126  props.insert( "spread", QString::number( mSpread ) );
129  props.insert( "color_type", QString::number( static_cast< int >( mColorType ) ) );
130  props.insert( "single_color", QgsSymbolLayerV2Utils::encodeColor( mColor ) );
131 
132  if ( mRamp )
133  {
134  props.unite( mRamp->properties() );
135  }
136 
137  return props;
138 }
139 
141 {
142  bool ok;
143  QPainter::CompositionMode mode = static_cast< QPainter::CompositionMode >( props.value( "blend_mode" ).toInt( &ok ) );
144  if ( ok )
145  {
146  mBlendMode = mode;
147  }
148  double transparency = props.value( "transparency" ).toDouble( &ok );
149  if ( ok )
150  {
152  }
153  mEnabled = props.value( "enabled", "1" ).toInt();
154  mDrawMode = static_cast< QgsPaintEffect::DrawMode >( props.value( "draw_mode", "2" ).toInt() );
155  int level = props.value( "blur_level" ).toInt( &ok );
156  if ( ok )
157  {
158  mBlurLevel = level;
159  }
160  double spread = props.value( "spread" ).toDouble( &ok );
161  if ( ok )
162  {
163  mSpread = spread;
164  }
165  mSpreadUnit = QgsSymbolLayerV2Utils::decodeOutputUnit( props.value( "spread_unit" ) );
166  mSpreadMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( props.value( "spread_unit_scale" ) );
167  QgsGlowEffect::GlowColorType type = static_cast< QgsGlowEffect::GlowColorType >( props.value( "color_type" ).toInt( &ok ) );
168  if ( ok )
169  {
170  mColorType = type;
171  }
172  if ( props.contains( "single_color" ) )
173  {
174  mColor = QgsSymbolLayerV2Utils::decodeColor( props.value( "single_color" ) );
175  }
176 
177  //attempt to create color ramp from props
178  delete mRamp;
179  mRamp = QgsVectorGradientColorRampV2::create( props );
180 }
181 
183 {
184  delete mRamp;
185  mRamp = ramp;
186 }
187 
189 {
190  if ( &rhs == this )
191  return *this;
192 
193  delete mRamp;
194 
195  mSpread = rhs.spread();
196  mRamp = rhs.ramp() ? rhs.ramp()->clone() : nullptr;
197  mBlurLevel = rhs.blurLevel();
198  mTransparency = rhs.transparency();
199  mColor = rhs.color();
200  mBlendMode = rhs.blendMode();
201  mColorType = rhs.colorType();
202 
203  return *this;
204 }
205 
206 QRectF QgsGlowEffect::boundingRect( const QRectF &rect, const QgsRenderContext& context ) const
207 {
208  //spread size
210  //plus possible extension due to blur, with a couple of extra pixels thrown in for safety
211  spread += mBlurLevel * 2 + 10;
212  return rect.adjusted( -spread, -spread, spread, spread );
213 }
214 
215 
216 //
217 // QgsOuterGlowEffect
218 //
219 
221  : QgsGlowEffect()
222 {
223 
224 }
225 
227 {
228 
229 }
230 
232 {
233  QgsOuterGlowEffect* effect = new QgsOuterGlowEffect();
234  effect->readProperties( map );
235  return effect;
236 }
237 
239 {
240  QgsOuterGlowEffect* newEffect = new QgsOuterGlowEffect( *this );
241  return newEffect;
242 }
243 
244 
245 //
246 // QgsInnerGlowEffect
247 //
248 
250  : QgsGlowEffect()
251 {
252 
253 }
254 
256 {
257 
258 }
259 
261 {
262  QgsInnerGlowEffect* effect = new QgsInnerGlowEffect();
263  effect->readProperties( map );
264  return effect;
265 }
266 
268 {
269  QgsInnerGlowEffect* newEffect = new QgsInnerGlowEffect( *this );
270  return newEffect;
271 }
static QString encodeOutputUnit(QgsSymbolV2::OutputUnit unit)
QgsVectorColorRampV2 * ramp() const
Returns the color ramp used for the glow.
QgsSymbolV2::OutputUnit mSpreadUnit
bool end()
bool contains(const Key &key) const
void setCompositionMode(CompositionMode mode)
virtual ~QgsOuterGlowEffect()
DrawMode mDrawMode
static void multiplyOpacity(QImage &image, const double factor)
Multiplies opacity of image pixel values by a factor.
void setRenderHint(RenderHint hint, bool on)
QMap< Key, T > & unite(const QMap< Key, T > &other)
static QString encodeColor(const QColor &color)
static void distanceTransform(QImage &image, const DistanceTransformProperties &properties)
Performs a distance transform on the source image and shades the result using a color ramp...
double transparency() const
Returns the transparency for the effect.
QPainter::CompositionMode mBlendMode
QgsGlowEffect & operator=(const QgsGlowEffect &rhs)
double spread
Maximum distance (in pixels) for the distance transform shading to spread.
bool enabled() const
Returns whether the effect is enabled.
Base class for visual effects which can be applied to QPicture drawings.
virtual void draw(QgsRenderContext &context) override
Handles drawing of the effect&#39;s result on to the specified render context.
void save()
void setAlpha(int alpha)
virtual QgsStringMap properties() const =0
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
QImage copy(const QRect &rectangle) const
bool shadeExterior
Set to true to perform the distance transform on transparent pixels in the source image...
virtual bool shadeExterior() const =0
Specifies whether the glow is drawn outside the picture or within the picture.
Base class for paint effect which draw a glow inside or outside a picture.
Definition: qgsgloweffect.h:34
static double pixelSizeScaleFactor(const QgsRenderContext &c, QgsSymbolV2::OutputUnit u, const QgsMapUnitScale &scale=QgsMapUnitScale())
Returns scale factor painter units -> pixel dimensions.
QImage * sourceAsImage(QgsRenderContext &context)
Returns the source QPicture rendered to a new QImage.
static QgsSymbolV2::OutputUnit decodeOutputUnit(const QString &str)
double mTransparency
QString number(int n, int base)
double spread() const
Returns the spread distance used for drawing the glow effect.
Definition: qgsgloweffect.h:67
GlowColorType mColorType
virtual QString type() const =0
Returns the effect type.
virtual QgsVectorColorRampV2 * clone() const =0
static QgsPaintEffect * create(const QgsStringMap &map)
Creates a new QgsOuterGlowEffect effect from a properties string map.
QgsVectorColorRampV2 * mRamp
GlowColorType
Color sources for the glow.
Definition: qgsgloweffect.h:40
QPointF imageOffset(const QgsRenderContext &context) const
Returns the offset which should be used when drawing the source image on to a destination render cont...
bool useMaxDistance
Set to true to automatically calculate the maximum distance in the transform to use as the spread val...
const QgsMapUnitScale & spreadMapUnitScale() const
Returns the map unit scale used for the spread distance.
Definition: qgsgloweffect.h:99
A paint effect which draws a glow outside of a picture.
DrawMode
Drawing modes for effects.
virtual ~QgsInnerGlowEffect()
virtual QgsOuterGlowEffect * clone() const override
Duplicates an effect by creating a deep copy of the effect.
static QgsVectorColorRampV2 * create(const QgsStringMap &properties=QgsStringMap())
QgsVectorColorRampV2 * ramp
Color ramp to use for shading the distance transform.
void restore()
void setRamp(QgsVectorColorRampV2 *ramp)
Sets the color ramp for the glow.
Contains information about the context of a rendering operation.
void drawImage(const QRectF &target, const QImage &image, const QRectF &source, QFlags< Qt::ImageConversionFlag > flags)
QPainter * painter()
int blurLevel() const
Returns the blur level (strength) for the glow.
static void stackBlur(QImage &image, const int radius, const bool alphaOnly=false)
Performs a stack blur on an image.
virtual QgsInnerGlowEffect * clone() const override
Duplicates an effect by creating a deep copy of the effect.
QgsMapUnitScale mSpreadMapUnitScale
virtual void readProperties(const QgsStringMap &props) override
Reads a string map of an effect&#39;s properties and restores the effect to the state described by the pr...
QColor color() const
Returns the color for the glow.
GlowColorType colorType() const
Returns the color mode used for the glow.
virtual QgsStringMap properties() const override
Returns the properties describing the paint effect encoded in a string format.
QRectF adjusted(qreal dx1, qreal dy1, qreal dx2, qreal dy2) const
virtual ~QgsGlowEffect()
static QColor decodeColor(const QString &str)
iterator insert(const Key &key, const T &value)
const QPicture * source() const
Returns the source QPicture.
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
A paint effect which draws a glow within a picture.
QgsSymbolV2::OutputUnit spreadUnit() const
Returns the units used for the glow spread distance.
Definition: qgsgloweffect.h:83
virtual QRectF boundingRect(const QRectF &rect, const QgsRenderContext &context) const override
Returns the bounding rect required for drawing the effect.
static QgsPaintEffect * create(const QgsStringMap &map)
Creates a new QgsInnerGlowEffect effect from a properties string map.
QPainter::CompositionMode blendMode() const
Returns the blend mode for the effect.
Struct for storing properties of a distance transform operation.
const T value(const Key &key) const