QGIS API Documentation  2.10.1-Pisa
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 
23  : QgsPaintEffect()
24  , mBlurLevel( 10 )
25  , mOffsetAngle( 135 )
26  , mOffsetDist( 2.0 )
27  , mOffsetUnit( QgsSymbolV2::MM )
28  , mTransparency( 0.0 )
29  , mColor( Qt::black )
30  , mBlendMode( QPainter::CompositionMode_Multiply )
31 {
32 
33 }
34 
36 {
37 
38 }
39 
41 {
42  if ( !source() || !enabled() || !context.painter() )
43  return;
44 
45  QImage colorisedIm = sourceAsImage( context )->copy();
46 
47  QPainter* painter = context.painter();
48  painter->save();
49  painter->setCompositionMode( mBlendMode );
50 
51  if ( !exteriorShadow() )
52  {
53  //inner shadow, first invert the opacity. The color does not matter since we will
54  //be replacing it anyway
55  colorisedIm.invertPixels( QImage::InvertRgba );
56  }
57 
60 
61  double offsetDist = mOffsetDist *
63 
64  double angleRad = mOffsetAngle * M_PI / 180; // to radians
65  QPointF transPt( -offsetDist * cos( angleRad + M_PI / 2 ),
66  -offsetDist * sin( angleRad + M_PI / 2 ) );
67 
68  //transparency, scale
70 
71  if ( !exteriorShadow() )
72  {
73  //inner shadow, do a bit of painter juggling
74  QImage innerShadowIm( colorisedIm.width(), colorisedIm.height(), QImage::Format_ARGB32 );
75  innerShadowIm.fill( Qt::transparent );
76  QPainter imPainter( &innerShadowIm );
77 
78  //draw shadow at offset
79  imPainter.drawImage( transPt.x(), transPt.y(), colorisedIm );
80 
81  //restrict shadow so it's only drawn on top of original image
82  imPainter.setCompositionMode( QPainter::CompositionMode_DestinationIn );
83  imPainter.drawImage( 0, 0, *sourceAsImage( context ) );
84  imPainter.end();
85 
86  painter->drawImage( imageOffset( context ), innerShadowIm );
87  }
88  else
89  {
90  painter->drawImage( imageOffset( context ) + transPt, colorisedIm );
91  }
92  painter->restore();
93 }
94 
96 {
97  QgsStringMap props;
98  props.insert( "enabled", mEnabled ? "1" : "0" );
99  props.insert( "draw_mode", QString::number( int( mDrawMode ) ) );
100  props.insert( "blend_mode", QString::number( int( mBlendMode ) ) );
101  props.insert( "transparency", QString::number( mTransparency ) );
102  props.insert( "blur_level", QString::number( mBlurLevel ) );
103  props.insert( "offset_angle", QString::number( mOffsetAngle ) );
104  props.insert( "offset_distance", QString::number( mOffsetDist ) );
107  props.insert( "color", QgsSymbolLayerV2Utils::encodeColor( mColor ) );
108  return props;
109 }
110 
112 {
113  bool ok;
114  QPainter::CompositionMode mode = ( QPainter::CompositionMode )props.value( "blend_mode" ).toInt( &ok );
115  if ( ok )
116  {
117  mBlendMode = mode;
118  }
119  double transparency = props.value( "transparency" ).toDouble( &ok );
120  if ( ok )
121  {
123  }
124  mEnabled = props.value( "enabled", "1" ).toInt();
125  mDrawMode = ( QgsPaintEffect::DrawMode )props.value( "draw_mode", "2" ).toInt();
126  int level = props.value( "blur_level" ).toInt( &ok );
127  if ( ok )
128  {
129  mBlurLevel = level;
130  }
131  int angle = props.value( "offset_angle" ).toInt( &ok );
132  if ( ok )
133  {
135  }
136  double distance = props.value( "offset_distance" ).toDouble( &ok );
137  if ( ok )
138  {
139  mOffsetDist = distance;
140  }
141  mOffsetUnit = QgsSymbolLayerV2Utils::decodeOutputUnit( props.value( "offset_unit" ) );
142  mOffsetMapUnitScale = QgsSymbolLayerV2Utils::decodeMapUnitScale( props.value( "offset_unit_scale" ) );
143  if ( props.contains( "color" ) )
144  {
145  mColor = QgsSymbolLayerV2Utils::decodeColor( props.value( "color" ) );
146  }
147 }
148 
149 QRectF QgsShadowEffect::boundingRect( const QRectF &rect, const QgsRenderContext& context ) const
150 {
151  //offset distance
153  //plus possible extension due to blur, with a couple of extra pixels thrown in for safety
154  spread += mBlurLevel * 2 + 10;
155  return rect.adjusted( -spread, -spread, spread, spread );
156 }
157 
158 
159 //
160 // QgsDropShadowEffect
161 //
162 
164 {
166  effect->readProperties( map );
167  return effect;
168 }
169 
171  : QgsShadowEffect()
172 {
173 
174 }
175 
177 {
178 
179 }
180 
182 {
183  return new QgsDropShadowEffect( *this );
184 }
185 
186 
187 //
188 // QgsInnerShadowEffect
189 //
190 
192 {
194  effect->readProperties( map );
195  return effect;
196 }
197 
199  : QgsShadowEffect()
200 {
201 
202 }
203 
205 {
206 
207 }
208 
210 {
211  return new QgsInnerShadowEffect( *this );
212 }
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.
bool enabled() const
Returns whether the effect is enabled.
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 QColor decodeColor(QString str)
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
QImage copy(const QRect &rectangle) const
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 QString encodeColor(QColor color)
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.
double transparency() const
Returns the transparency for the effect.
#define M_PI
QPainter::CompositionMode mBlendMode
QPointF imageOffset(const QgsRenderContext &context) const
Returns the offset which should be used when drawing the source image on to a destination render cont...
virtual ~QgsShadowEffect()
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's result on to the specified render context.
DrawMode
Drawing modes for effects.
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'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
iterator insert(const Key &key, const T &value)
const QPicture * source() const
Returns the source QPicture.
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
virtual QgsPaintEffect * clone() const override
Duplicates an effect by creating a deep copy of the effect.
virtual QgsPaintEffect * clone() const override
Duplicates an effect by creating a deep copy of the effect.
static QgsSymbolV2::OutputUnit decodeOutputUnit(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.