QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
qgsshadoweffect.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsshadoweffect.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 "qgsshadoweffect.h"
19 #include "qgsimageoperation.h"
20 #include "qgssymbollayerv2utils.h"
21 #include "qgsunittypes.h"
22 
24  : QgsPaintEffect()
25  , mBlurLevel( 10 )
26  , mOffsetAngle( 135 )
27  , mOffsetDist( 2.0 )
28  , mOffsetUnit( QgsSymbolV2::MM )
29  , mTransparency( 0.0 )
30  , mColor( Qt::black )
31  , mBlendMode( QPainter::CompositionMode_Multiply )
32 {
33 
34 }
35 
37 {
38 
39 }
40 
42 {
43  if ( !source() || !enabled() || !context.painter() )
44  return;
45 
46  QImage colorisedIm = sourceAsImage( context )->copy();
47 
48  QPainter* painter = context.painter();
49  painter->save();
50  painter->setCompositionMode( mBlendMode );
51 
52  if ( !exteriorShadow() )
53  {
54  //inner shadow, first invert the opacity. The color does not matter since we will
55  //be replacing it anyway
56  colorisedIm.invertPixels( QImage::InvertRgba );
57  }
58 
61 
62  double offsetDist = mOffsetDist *
64 
65  double angleRad = mOffsetAngle * M_PI / 180; // to radians
66  QPointF transPt( -offsetDist * cos( angleRad + M_PI / 2 ),
67  -offsetDist * sin( angleRad + M_PI / 2 ) );
68 
69  //transparency, scale
71 
72  if ( !exteriorShadow() )
73  {
74  //inner shadow, do a bit of painter juggling
75  QImage innerShadowIm( colorisedIm.width(), colorisedIm.height(), QImage::Format_ARGB32 );
76  innerShadowIm.fill( Qt::transparent );
77  QPainter imPainter( &innerShadowIm );
78 
79  //draw shadow at offset
80  imPainter.drawImage( transPt.x(), transPt.y(), colorisedIm );
81 
82  //restrict shadow so it's only drawn on top of original image
83  imPainter.setCompositionMode( QPainter::CompositionMode_DestinationIn );
84  imPainter.drawImage( 0, 0, *sourceAsImage( context ) );
85  imPainter.end();
86 
87  painter->drawImage( imageOffset( context ), innerShadowIm );
88  }
89  else
90  {
91  painter->drawImage( imageOffset( context ) + transPt, colorisedIm );
92  }
93  painter->restore();
94 }
95 
97 {
98  QgsStringMap props;
99  props.insert( "enabled", mEnabled ? "1" : "0" );
100  props.insert( "draw_mode", QString::number( int( mDrawMode ) ) );
101  props.insert( "blend_mode", QString::number( int( mBlendMode ) ) );
102  props.insert( "transparency", QString::number( mTransparency ) );
103  props.insert( "blur_level", QString::number( mBlurLevel ) );
104  props.insert( "offset_angle", QString::number( mOffsetAngle ) );
105  props.insert( "offset_distance", QString::number( mOffsetDist ) );
108  props.insert( "color", QgsSymbolLayerV2Utils::encodeColor( mColor ) );
109  return props;
110 }
111 
113 {
114  bool ok;
115  QPainter::CompositionMode mode = static_cast< QPainter::CompositionMode >( props.value( "blend_mode" ).toInt( &ok ) );
116  if ( ok )
117  {
118  mBlendMode = mode;
119  }
120  double transparency = props.value( "transparency" ).toDouble( &ok );
121  if ( ok )
122  {
124  }
125  mEnabled = props.value( "enabled", "1" ).toInt();
126  mDrawMode = static_cast< QgsPaintEffect::DrawMode >( props.value( "draw_mode", "2" ).toInt() );
127  int level = props.value( "blur_level" ).toInt( &ok );
128  if ( ok )
129  {
130  mBlurLevel = level;
131  }
132  int angle = props.value( "offset_angle" ).toInt( &ok );
133  if ( ok )
134  {
136  }
137  double distance = props.value( "offset_distance" ).toDouble( &ok );
138  if ( ok )
139  {
140  mOffsetDist = distance;
141  }
142  mOffsetUnit = QgsSymbolLayerV2Utils::decodeOutputUnit( props.value( "offset_unit" ) );
143  mOffsetMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( props.value( "offset_unit_scale" ) );
144  if ( props.contains( "color" ) )
145  {
146  mColor = QgsSymbolLayerV2Utils::decodeColor( props.value( "color" ) );
147  }
148 }
149 
150 QRectF QgsShadowEffect::boundingRect( const QRectF &rect, const QgsRenderContext& context ) const
151 {
152  //offset distance
154  //plus possible extension due to blur, with a couple of extra pixels thrown in for safety
155  spread += mBlurLevel * 2 + 10;
156  return rect.adjusted( -spread, -spread, spread, spread );
157 }
158 
159 
160 //
161 // QgsDropShadowEffect
162 //
163 
165 {
167  effect->readProperties( map );
168  return effect;
169 }
170 
172  : QgsShadowEffect()
173 {
174 
175 }
176 
178 {
179 
180 }
181 
183 {
184  return new QgsDropShadowEffect( *this );
185 }
186 
187 
188 //
189 // QgsInnerShadowEffect
190 //
191 
193 {
195  effect->readProperties( map );
196  return effect;
197 }
198 
200  : QgsShadowEffect()
201 {
202 
203 }
204 
206 {
207 
208 }
209 
211 {
212  return new QgsInnerShadowEffect( *this );
213 }
static QString encodeOutputUnit(QgsSymbolV2::OutputUnit unit)
static void overlayColor(QImage &image, const QColor &color)
Overlays a color onto an image.
bool end()
bool contains(const Key &key) const
void setCompositionMode(CompositionMode mode)
DrawMode mDrawMode
static void multiplyOpacity(QImage &image, const double factor)
Multiplies opacity of image pixel values by a factor.
static QString encodeColor(const QColor &color)
Base class for visual effects which can be applied to QPicture drawings.
void save()
virtual QgsStringMap properties() const override
Returns the properties describing the paint effect encoded in a string format.
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
QImage copy(const QRect &rectangle) const
virtual QgsDropShadowEffect * clone() const override
Duplicates an effect by creating a deep copy of the effect.
virtual bool exteriorShadow() const =0
Specifies whether the shadow is drawn outside the picture or within the picture.
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)
QPointF imageOffset(const QgsRenderContext &context) const
Returns the offset which should be used when drawing the source image on to a destination render cont...
QgsMapUnitScale mOffsetMapUnitScale
QString number(int n, int base)
qreal x() const
qreal y() const
void fill(uint pixelValue)
int width() const
virtual QRectF boundingRect(const QRectF &rect, const QgsRenderContext &context) const override
Returns the bounding rect required for drawing the effect.
#define M_PI
QPainter::CompositionMode mBlendMode
bool enabled() const
Returns whether the effect is enabled.
virtual ~QgsShadowEffect()
double transparency() const
Returns the transparency for the effect.
A paint effect which draws an offset and optionally blurred drop shadow.
double ANALYSIS_EXPORT angle(Point3D *p1, Point3D *p2, Point3D *p3, Point3D *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
virtual void draw(QgsRenderContext &context) override
Handles drawing of the effect&#39;s result on to the specified render context.
DrawMode
Drawing modes for effects.
virtual QgsInnerShadowEffect * clone() const override
Duplicates an effect by creating a deep copy of the effect.
void invertPixels(InvertMode mode)
void restore()
A paint effect which draws an offset and optionally blurred drop shadow within a picture.
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()
static void stackBlur(QImage &image, const int radius, const bool alphaOnly=false)
Performs a stack blur on an image.
QgsSymbolV2::OutputUnit mOffsetUnit
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...
static QgsPaintEffect * create(const QgsStringMap &map)
Creates a new QgsInnerShadowEffect effect from a properties string map.
Base class for paint effects which offset, blurred shadows.
QRectF adjusted(qreal dx1, qreal dy1, qreal dx2, qreal dy2) const
int height() const
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)
const T value(const Key &key) const
static QgsPaintEffect * create(const QgsStringMap &map)
Creates a new QgsDropShadowEffect effect from a properties string map.