Skip to content
Permalink
Browse files

[FEATURE] Paint effects for layers and symbol layers

This commit adds a new framework for implementing paint effects, which
modify the results of QPainter operations to apply visual effects
such as drop shadows and blurs.

The initial implementation allows for effects to be applied to entire
layers and individual symbol layers.

Included are a drop shadow, inner shadow, blur, inner glow, outer glow,
colorise and transform effect. A "stack" effect is also implemented
which allows other paint effects to be combined in various ways.

Sponsored by hundreds of generous kickstarter contributors!
  • Loading branch information
nyalldawson committed Mar 28, 2015
1 parent fe2db52 commit 742f3233eed8170f7ba47e3eaadfdca24621c0a3
Showing with 11,650 additions and 179 deletions.
  1. +1 −0 images/images.qrc
  2. +127 −0 images/themes/default/mIconPaintEffects.svg
  3. +2 −0 python/CMakeLists.txt
  4. +8 −0 python/core/core.sip
  5. +99 −0 python/core/effects/qgsblureffect.sip
  6. +174 −0 python/core/effects/qgscoloreffect.sip
  7. +108 −0 python/core/effects/qgseffectstack.sip
  8. +253 −0 python/core/effects/qgsgloweffect.sip
  9. +301 −0 python/core/effects/qgspainteffect.sip
  10. +111 −0 python/core/effects/qgspainteffectregistry.sip
  11. +218 −0 python/core/effects/qgsshadoweffect.sip
  12. +204 −0 python/core/effects/qgstransformeffect.sip
  13. +20 −0 python/core/symbology-ng/qgsrendererv2.sip
  14. +22 −2 python/core/symbology-ng/qgssymbollayerv2.sip
  15. +11 −0 python/core/symbology-ng/qgssymbollayerv2utils.sip
  16. +30 −0 python/gui/effects/qgseffectdrawmodecombobox.sip
  17. +191 −0 python/gui/effects/qgseffectstackpropertieswidget.sip
  18. +43 −0 python/gui/effects/qgspainteffectpropertieswidget.sip
  19. +109 −0 python/gui/effects/qgspainteffectwidget.sip
  20. +5 −0 python/gui/gui.sip
  21. +16 −0 src/core/CMakeLists.txt
  22. +137 −0 src/core/effects/qgsblureffect.cpp
  23. +132 −0 src/core/effects/qgsblureffect.h
  24. +129 −0 src/core/effects/qgscoloreffect.cpp
  25. +210 −0 src/core/effects/qgscoloreffect.h
  26. +253 −0 src/core/effects/qgseffectstack.cpp
  27. +136 −0 src/core/effects/qgseffectstack.h
  28. +270 −0 src/core/effects/qgsgloweffect.cpp
  29. +286 −0 src/core/effects/qgsgloweffect.h
  30. +38 −10 src/core/effects/qgsimageoperation.cpp
  31. +3 −4 src/core/effects/qgsimageoperation.h
  32. +309 −0 src/core/effects/qgspainteffect.cpp
  33. +302 −0 src/core/effects/qgspainteffect.h
  34. +115 −0 src/core/effects/qgspainteffectregistry.cpp
  35. +201 −0 src/core/effects/qgspainteffectregistry.h
  36. +212 −0 src/core/effects/qgsshadoweffect.cpp
  37. +243 −0 src/core/effects/qgsshadoweffect.h
  38. +150 −0 src/core/effects/qgstransformeffect.cpp
  39. +245 −0 src/core/effects/qgstransformeffect.h
  40. +0 −1 src/core/qgsmaprenderercustompainterjob.cpp
  41. +14 −0 src/core/qgsvectorlayerrenderer.cpp
  42. +6 −0 src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp
  43. +8 −0 src/core/symbology-ng/qgsfillsymbollayerv2.cpp
  44. +5 −0 src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp
  45. +5 −0 src/core/symbology-ng/qgsheatmaprenderer.cpp
  46. +5 −0 src/core/symbology-ng/qgsinvertedpolygonrenderer.cpp
  47. +2 −0 src/core/symbology-ng/qgslinesymbollayerv2.cpp
  48. +3 −0 src/core/symbology-ng/qgsmarkersymbollayerv2.cpp
  49. +6 −0 src/core/symbology-ng/qgspointdisplacementrenderer.cpp
  50. +49 −5 src/core/symbology-ng/qgsrendererv2.cpp
  51. +26 −2 src/core/symbology-ng/qgsrendererv2.h
  52. +5 −0 src/core/symbology-ng/qgsrulebasedrendererv2.cpp
  53. +5 −0 src/core/symbology-ng/qgssinglesymbolrendererv2.cpp
  54. +38 −0 src/core/symbology-ng/qgssymbollayerv2.cpp
  55. +24 −5 src/core/symbology-ng/qgssymbollayerv2.h
  56. +26 −0 src/core/symbology-ng/qgssymbollayerv2utils.cpp
  57. +10 −0 src/core/symbology-ng/qgssymbollayerv2utils.h
  58. +127 −18 src/core/symbology-ng/qgssymbolv2.cpp
  59. +23 −0 src/core/symbology-ng/qgssymbolv2.h
  60. +12 −0 src/gui/CMakeLists.txt
  61. +47 −0 src/gui/effects/qgseffectdrawmodecombobox.cpp
  62. +49 −0 src/gui/effects/qgseffectdrawmodecombobox.h
  63. +471 −0 src/gui/effects/qgseffectstackpropertieswidget.cpp
  64. +241 −0 src/gui/effects/qgseffectstackpropertieswidget.h
  65. +169 −0 src/gui/effects/qgspainteffectpropertieswidget.cpp
  66. +72 −0 src/gui/effects/qgspainteffectpropertieswidget.h
  67. +1,059 −0 src/gui/effects/qgspainteffectwidget.cpp
  68. +264 −0 src/gui/effects/qgspainteffectwidget.h
  69. +7 −0 src/gui/symbology-ng/qgslayerpropertieswidget.cpp
  70. +17 −1 src/gui/symbology-ng/qgsrendererv2propertiesdialog.cpp
  71. +4 −1 src/gui/symbology-ng/qgsrendererv2propertiesdialog.h
  72. +2 −1 src/ui/CMakeLists.txt
  73. +69 −0 src/ui/effects/qgseffectpropertieswidget.ui
  74. +194 −0 src/ui/effects/qgseffectstackpropertieswidgetbase.ui
  75. +186 −0 src/ui/effects/widget_blur.ui
  76. +484 −0 src/ui/effects/widget_coloreffects.ui
  77. +154 −0 src/ui/effects/widget_drawsource.ui
  78. +357 −0 src/ui/effects/widget_glow.ui
  79. +313 −0 src/ui/effects/widget_shadoweffect.ui
  80. +315 −0 src/ui/effects/widget_transform.ui
  81. +449 −106 src/ui/qgslabelingguibase.ui
  82. +30 −5 src/ui/qgsrendererv2propsdialogbase.ui
  83. +9 −9 src/ui/qgsvectorlayerpropertiesbase.ui
  84. +26 −6 src/ui/symbollayer/widget_layerproperties.ui
  85. +2 −0 tests/src/core/CMakeLists.txt
  86. +5 −3 tests/src/core/testqgsimageoperation.cpp
  87. +669 −0 tests/src/core/testqgspainteffect.cpp
  88. +163 −0 tests/src/core/testqgspainteffectregistry.cpp
  89. BIN tests/testdata/control_images/expected_imageop_dt_interior/expected_imageop_dt_interior.png
  90. BIN tests/testdata/control_images/expected_imageop_dt_max/expected_imageop_dt_max.png
  91. BIN tests/testdata/control_images/expected_imageop_dt_spread/expected_imageop_dt_spread.png
  92. BIN tests/testdata/control_images/expected_painteffect_blur/expected_painteffect_blur.png
  93. BIN tests/testdata/control_images/expected_painteffect_blur/painteffect_blur.png
  94. BIN tests/testdata/control_images/expected_painteffect_drawsource/expected_painteffect_drawsource.png
  95. BIN tests/testdata/control_images/expected_painteffect_dropshadow/expected_painteffect_dropshadow.png
  96. BIN .../testdata/control_images/expected_painteffect_dropshadow/expected_painteffect_dropshadow_mask.png
  97. BIN tests/testdata/control_images/expected_painteffect_outerglow/expected_painteffect_outerglow.png
  98. BIN tests/testdata/control_images/expected_painteffect_stack/expected_painteffect_stack.png
  99. BIN tests/testdata/sample_alpha_image.png
@@ -479,6 +479,7 @@
<file>themes/default/bubble.svg</file>
<file>themes/default/mIconClear.png</file>
<file>flags/zh.png</file>
<file>themes/default/mIconPaintEffects.svg</file>
</qresource>
<qresource prefix="/images/tips">
<file alias="symbol_levels.png">qgis_tips/symbol_levels.png</file>
@@ -0,0 +1,127 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
viewBox="0 0 16 16"
id="svg2"
version="1.1"
inkscape:version="0.91 r"
sodipodi:docname="mIconPaintEffects.svg">
<defs
id="defs4">
<filter
inkscape:collect="always"
style="color-interpolation-filters:sRGB"
id="filter4772"
x="-0.25463846"
width="1.5092769"
y="-0.2664283"
height="1.5328566">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="1.0089486"
id="feGaussianBlur4774" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.4"
inkscape:cx="12.616664"
inkscape:cy="9.8282636"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:window-width="1215"
inkscape:window-height="776"
inkscape:window-x="65"
inkscape:window-y="24"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid4138" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
<path
sodipodi:type="star"
style="opacity:0.83600003;fill:#333333;stroke:#1a1a1a;filter:url(#filter4772)"
id="path4326"
sodipodi:sides="5"
sodipodi:cx="9.8839276"
sodipodi:cy="1046.5587"
sodipodi:r1="5"
sodipodi:r2="2.5"
sodipodi:arg1="0.92729522"
sodipodi:arg2="1.5556137"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 12.883927,1050.5587 -2.9620445,-1.5003 -2.9151302,1.5896 0.5115366,-3.2807 -2.4125535,-2.2813 3.2781918,-0.5273 1.4240902,-2.9994 1.5144976,2.9548 3.292689,0.4275 -2.342181,2.3535 z"
inkscape:transform-center-x="0.023457472"
inkscape:transform-center-y="-0.4550931" />
<path
sodipodi:type="star"
style="fill:#ff6a00;fill-opacity:1;stroke:#ffffff;stroke-width:2.852;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
id="path4326-4-4"
sodipodi:sides="5"
sodipodi:cx="7.4186501"
sodipodi:cy="1044.0542"
sodipodi:r1="5.7612567"
sodipodi:r2="2.8806283"
sodipodi:arg1="0.92729522"
sodipodi:arg2="1.5556137"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 10.875404,1048.6632 -3.41302,-1.7287 -3.3589627,1.8315 0.5894187,-3.7801 -2.779868,-2.6286 3.777301,-0.6076 1.6409098,-3.4561 1.7450817,3.4047 3.7940055,0.4926 -2.698781,2.7118 z"
inkscape:transform-center-x="0.027028932"
inkscape:transform-center-y="-0.52443508" />
<path
sodipodi:type="star"
style="fill:#fff400;fill-opacity:1;stroke:#ea9615;stroke-width:1.15225136;stroke-opacity:1"
id="path4326-4"
sodipodi:sides="5"
sodipodi:cx="7.3740072"
sodipodi:cy="1044.0364"
sodipodi:r1="5.7612567"
sodipodi:r2="2.8806283"
sodipodi:arg1="0.92729522"
sodipodi:arg2="1.5556137"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 10.830761,1048.6454 -3.41302,-1.7287 -3.3589626,1.8315 0.5894187,-3.7802 -2.779868,-2.6286 3.777301,-0.6075 1.6409098,-3.4561 1.7450816,3.4047 3.7940065,0.4926 -2.698782,2.7117 z"
inkscape:transform-center-x="0.027028932"
inkscape:transform-center-y="-0.52443508" />
</g>
</svg>
@@ -92,6 +92,7 @@ INCLUDE_DIRECTORIES(
../src/gui/attributetable
../src/gui/editorwidgets
../src/gui/editorwidgets/core
../src/gui/effects
../src/gui/layertree

${CMAKE_BINARY_DIR} # qgsconfig.h, qgsversion.h
@@ -144,6 +145,7 @@ ADD_SIP_PYTHON_MODULE(qgis._core core/core.sip qgis_core)
INCLUDE_DIRECTORIES(
../src/gui
../src/gui/symbology-ng
../src/gui/effects
../src/plugins
${CMAKE_BINARY_DIR}/src/gui
${CMAKE_BINARY_DIR}/src/ui
@@ -174,6 +174,14 @@
%Include diagram/qgstextdiagram.sip

%Include effects/qgsimageoperation.sip
%Include effects/qgspainteffect.sip
%Include effects/qgseffectstack.sip
%Include effects/qgsblureffect.sip
%Include effects/qgsshadoweffect.sip
%Include effects/qgsgloweffect.sip
%Include effects/qgstransformeffect.sip
%Include effects/qgscoloreffect.sip
%Include effects/qgspainteffectregistry.sip

%Include gps/qgsgpsconnection.sip
%Include gps/qgsgpsconnectionregistry.sip
@@ -0,0 +1,99 @@
/** \ingroup core
* \class QgsBlurEffect
* \brief A paint effect which blurs a source picture, using a number of different blur
* methods.
*
* \note Added in version 2.9
*/

class QgsBlurEffect : QgsPaintEffect
{
%TypeHeaderCode
#include <qgsblureffect.h>
%End

public:

/** Available blur methods (algorithms) */
enum BlurMethod
{
StackBlur, /*< stack blur, a fast but low quality blur. Valid blur level values are between 0 - 16.*/
GaussianBlur /*< Gaussian blur, a slower but high quality blur. Blur level values are the distance in pixels for the blur operation. */
};

/** Creates a new QgsBlurEffect effect from a properties string map.
* @param map encoded properties string map
* @returns new QgsBlurEffect
*/
static QgsPaintEffect* create( const QgsStringMap& ) /Factory/;

QgsBlurEffect();
virtual ~QgsBlurEffect();

virtual QString type() const;
virtual QgsStringMap properties() const;
virtual void readProperties( const QgsStringMap& props );
virtual QgsPaintEffect* clone() const /Factory/;

/** Sets blur level (strength)
* @param level blur level. Depending on the current @link blurMethod @endlink, this parameter
* has different effects
* @see blurLevel
* @see blurMethod
*/
void setBlurLevel( const int level );

/** Returns the blur level (strength)
* @returns blur level. Depending on the current @link blurMethod @endlink, this parameter
* has different effects
* @see setBlurLevel
* @see blurMethod
*/
int blurLevel() const;

/** Sets the blur method (algorithm) to use for performing the blur.
* @param method blur method
* @see blurMethod
*/
void setBlurMethod( const BlurMethod method );

/** Returns the blur method (algorithm) used for performing the blur.
* @returns blur method
* @see setBlurMethod
*/
BlurMethod blurMethod() const;

/** Sets the transparency for the effect
* @param transparency double between 0 and 1 inclusive, where 0 is fully opaque
* and 1 is fully transparent
* @see transparency
*/
void setTransparency( const double transparency );

/** Returns the transparency for the effect
* @returns transparency value between 0 and 1 inclusive, where 0 is fully opaque
* and 1 is fully transparent
* @see setTransparency
*/
double transparency() const;

/** Sets the blend mode for the effect
* @param mode blend mode used for drawing the effect on to a destination
* paint device
* @see blendMode
*/
void setBlendMode( const QPainter::CompositionMode mode );

/** Returns the blend mode for the effect
* @returns blend mode used for drawing the effect on to a destination
* paint device
* @see setBlendMode
*/
QPainter::CompositionMode blendMode() const;

protected:

virtual void draw( QgsRenderContext& context );
virtual QRectF boundingRect( const QRectF& rect, const QgsRenderContext& context ) const;

};

0 comments on commit 742f323

Please sign in to comment.
You can’t perform that action at this time.