1/**************************************************************************** 2** 3** Copyright (C) 2016 The Qt Company Ltd. 4** Contact: https://www.qt.io/licensing/ 5** 6** This file is part of the Qt Graphical Effects module. 7** 8** $QT_BEGIN_LICENSE:BSD$ 9** Commercial License Usage 10** Licensees holding valid commercial Qt licenses may use this file in 11** accordance with the commercial license agreement provided with the 12** Software or, alternatively, in accordance with the terms contained in 13** a written agreement between you and The Qt Company. For licensing terms 14** and conditions see https://www.qt.io/terms-conditions. For further 15** information use the contact form at https://www.qt.io/contact-us. 16** 17** BSD License Usage 18** Alternatively, you may use this file under the terms of the BSD license 19** as follows: 20** 21** "Redistribution and use in source and binary forms, with or without 22** modification, are permitted provided that the following conditions are 23** met: 24** * Redistributions of source code must retain the above copyright 25** notice, this list of conditions and the following disclaimer. 26** * Redistributions in binary form must reproduce the above copyright 27** notice, this list of conditions and the following disclaimer in 28** the documentation and/or other materials provided with the 29** distribution. 30** * Neither the name of The Qt Company Ltd nor the names of its 31** contributors may be used to endorse or promote products derived 32** from this software without specific prior written permission. 33** 34** 35** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 36** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 37** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 38** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 39** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 41** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 42** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 43** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 44** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 45** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 46** 47** $QT_END_LICENSE$ 48** 49****************************************************************************/ 50 51import QtQuick 2.0 52import "private" 53 54/*! 55 \qmltype RadialGradient 56 \inqmlmodule QtGraphicalEffects 1.0 57 \since QtGraphicalEffects 1.0 58 \inherits QtQuick2::Item 59 \ingroup qtgraphicaleffects-gradient 60 \brief Draws a radial gradient. 61 62 A gradient is defined by two or more colors, which are blended seamlessly. 63 The colors start from the middle of the item and end at the borders. 64 65 \table 66 \header 67 \li Effect applied 68 \row 69 \li \image RadialGradient.png 70 \endtable 71 72 \section1 Example 73 74 The following example shows how to apply the effect. 75 \snippet RadialGradient-example.qml example 76 77*/ 78Item { 79 id: rootItem 80 81 /*! 82 This property allows the effect output pixels to be cached in order to 83 improve the rendering performance. 84 85 Every time the source or effect properties are changed, the pixels in 86 the cache must be updated. Memory consumption is increased, because an 87 extra buffer of memory is required for storing the effect output. 88 89 It is recommended to disable the cache when the source or the effect 90 properties are animated. 91 92 By default, the property is set to \c false. 93 */ 94 property bool cached: false 95 96 /*! 97 The HorizontalOffset and verticalOffset properties define the offset in 98 pixels for the center point of the gradient compared to the item center. 99 100 The values range from -inf to inf. By default, these properties are set 101 to \c 0. 102 103 \table 104 \header 105 \li Output examples with different horizontalOffset values 106 \li 107 \li 108 \row 109 \li \image RadialGradient_horizontalOffset1.png 110 \li \image RadialGradient_horizontalOffset2.png 111 \li \image RadialGradient_horizontalOffset3.png 112 \row 113 \li \b { horizontalOffset: -150 } 114 \li \b { horizontalOffset: 0 } 115 \li \b { horizontalOffset: 150 } 116 \row 117 \li \l verticalOffset: 0 118 \li \l verticalOffset: 0 119 \li \l verticalOffset: 0 120 \row 121 \li \l horizontalRadius: 300 122 \li \l horizontalRadius: 300 123 \li \l horizontalRadius: 300 124 \row 125 \li \l verticalRadius: 300 126 \li \l verticalRadius: 300 127 \li \l verticalRadius: 300 128 \row 129 \li \l angle: 0 130 \li \l angle: 0 131 \li \l angle: 0 132 \endtable 133 134 */ 135 property real horizontalOffset: 0.0 136 property real verticalOffset: 0.0 137 138 /*! 139 The HorizontalRadius and verticalRadius properties define the shape and 140 size of the radial gradient. If the radiuses are equal, the shape of the 141 gradient is a circle. If the horizontal and vertical radiuses differ, 142 the shape is elliptical. The radiuses are given in pixels. 143 144 The value ranges from -inf to inf. By default, horizontalRadius is bound 145 to width and verticalRadius is bound to height. 146 147 \table 148 \header 149 \li Output examples with different horizontalRadius values 150 \li 151 \li 152 \row 153 \li \image RadialGradient_horizontalRadius1.png 154 \li \image RadialGradient_horizontalRadius2.png 155 \row 156 \li \b { horizontalRadius: 300 } 157 \li \b { horizontalRadius: 100 } 158 \row 159 \li \l horizontalOffset: 0 160 \li \l horizontalOffset: 0 161 \row 162 \li \l verticalOffset: 0 163 \li \l verticalOffset: 0 164 \row 165 \li \l verticalRadius: 300 166 \li \l verticalRadius: 300 167 \row 168 \li \l angle: 0 169 \li \l angle: 0 170 \row 171 \li \l gradient: QQuickGradient(0xa05fb10) 172 \li \l gradient: QQuickGradient(0xa05fb10) 173 \endtable 174 175 */ 176 property real horizontalRadius: width 177 property real verticalRadius: height 178 179 /*! 180 This property defines the rotation of the gradient around its center 181 point. The rotation is only visible when the 182 \l{RadialGradient::horizontalRadius}{horizontalRadius} and 183 \l{RadialGradient::verticalRadius}{verticalRadius} properties are not 184 equal. The angle is given in degrees and the default value is \c 0. 185 186 \table 187 \header 188 \li Output examples with different angle values 189 \li 190 \li 191 \row 192 \li \image RadialGradient_angle1.png 193 \li \image RadialGradient_angle2.png 194 \li \image RadialGradient_angle3.png 195 \row 196 \li \b { angle: 0 } 197 \li \b { angle: 45 } 198 \li \b { angle: 90 } 199 \row 200 \li \l horizontalOffset: 0 201 \li \l horizontalOffset: 0 202 \li \l horizontalOffset: 0 203 \row 204 \li \l verticalOffset: 0 205 \li \l verticalOffset: 0 206 \li \l verticalOffset: 0 207 \row 208 \li \l horizontalRadius: 100 209 \li \l horizontalRadius: 100 210 \li \l horizontalRadius: 100 211 \row 212 \li \l verticalRadius: 300 213 \li \l verticalRadius: 300 214 \li \l verticalRadius: 300 215 \endtable 216 */ 217 property real angle: 0.0 218 219 /*! 220 This property defines the item that is going to be filled with gradient. 221 Source item gets rendered into an intermediate pixel buffer and the 222 alpha values from the result are used to determine the gradient's pixels 223 visibility in the display. The default value for source is undefined and 224 in that case whole effect area is filled with gradient. 225 226 \table 227 \header 228 \li Output examples with different source values 229 \li 230 \li 231 \row 232 \li \image RadialGradient_maskSource1.png 233 \li \image RadialGradient_maskSource2.png 234 \row 235 \li \b { source: undefined } 236 \li \b { source: Image { source: images/butterfly.png } } 237 \row 238 \li \l horizontalOffset: 0 239 \li \l horizontalOffset: 0 240 \row 241 \li \l verticalOffset: 0 242 \li \l verticalOffset: 0 243 \row 244 \li \l horizontalRadius: 300 245 \li \l horizontalRadius: 300 246 \row 247 \li \l verticalRadius: 300 248 \li \l verticalRadius: 300 249 \row 250 \li \l angle: 0 251 \li \l angle: 0 252 \endtable 253 254 \note It is not supported to let the effect include itself, for 255 instance by setting source to the effect's parent. 256 */ 257 property variant source 258 259 /*! 260 A gradient is defined by two or more colors, which are blended 261 seamlessly. The colors are specified as a set of GradientStop child 262 items, each of which defines a position on the gradient from 0.0 to 1.0 263 and a color. The position of each GradientStop is defined by setting the 264 position property. The color is defined by setting the color property. 265 266 \table 267 \header 268 \li Output examples with different gradient values 269 \li 270 \li 271 \row 272 \li \image RadialGradient_gradient1.png 273 \li \image RadialGradient_gradient2.png 274 \li \image RadialGradient_gradient3.png 275 \row 276 \li \b {gradient:} \code 277 Gradient { 278 GradientStop { position: 0.000 279 color: Qt.rgba(1, 0, 0, 1) } 280 GradientStop { position: 0.167; 281 color: Qt.rgba(1, 1, 0, 1) } 282 GradientStop { position: 0.333; 283 color: Qt.rgba(0, 1, 0, 1) } 284 GradientStop { position: 0.500; 285 color: Qt.rgba(0, 1, 1, 1) } 286 GradientStop { position: 0.667; 287 color: Qt.rgba(0, 0, 1, 1) } 288 GradientStop { position: 0.833; 289 color: Qt.rgba(1, 0, 1, 1) } 290 GradientStop { position: 1.000; 291 color: Qt.rgba(1, 0, 0, 1) } 292 } 293 \endcode 294 \li \b {gradient:} \code 295 Gradient { 296 GradientStop { position: 0.0 297 color: "#F0F0F0" 298 } 299 GradientStop { position: 0.5 300 color: "#000000" 301 } 302 GradientStop { position: 1.0 303 color: "#F0F0F0" 304 } 305 } 306 \endcode 307 \li \b {gradient:} 308 \code 309 Gradient { 310 GradientStop { position: 0.0 311 color: "#00000000" 312 } 313 GradientStop { position: 1.0 314 color: "#FF000000" 315 } 316 } 317 \endcode 318 \row 319 \li \l horizontalOffset: 0 320 \li \l horizontalOffset: 0 321 \li \l horizontalOffset: 0 322 \row 323 \li \l verticalOffset: 0 324 \li \l verticalOffset: 0 325 \li \l verticalOffset: 0 326 \row 327 \li \l horizontalRadius: 300 328 \li \l horizontalRadius: 300 329 \li \l horizontalRadius: 300 330 \row 331 \li \l verticalRadius: 300 332 \li \l verticalRadius: 300 333 \li \l verticalRadius: 300 334 \row 335 \li \l angle: 0 336 \li \l angle: 0 337 \li \l angle: 0 338 \endtable 339 */ 340 property Gradient gradient: Gradient { 341 GradientStop { position: 0.0; color: "white" } 342 GradientStop { position: 1.0; color: "black" } 343 } 344 345 SourceProxy { 346 id: maskSourceProxy 347 input: rootItem.source 348 } 349 350 ShaderEffectSource { 351 id: gradientSource 352 sourceItem: Rectangle { 353 width: 16 354 height: 256 355 gradient: rootItem.gradient 356 smooth: true 357 } 358 smooth: true 359 hideSource: true 360 visible: false 361 } 362 363 ShaderEffectSource { 364 id: cacheItem 365 anchors.fill: parent 366 visible: rootItem.cached 367 smooth: true 368 sourceItem: shaderItem 369 live: true 370 hideSource: visible 371 } 372 373 ShaderEffect { 374 id: shaderItem 375 property variant gradientImage: gradientSource 376 property variant maskSource: maskSourceProxy.output 377 property variant center: Qt.point(0.5 + rootItem.horizontalOffset / width, 0.5 + rootItem.verticalOffset / height) 378 property real horizontalRatio: rootItem.horizontalRadius > 0 ? width / (2 * rootItem.horizontalRadius) : width * 16384 379 property real verticalRatio: rootItem.verticalRadius > 0 ? height / (2 * rootItem.verticalRadius) : height * 16384 380 property real angle: -rootItem.angle / 360 * 2 * Math.PI 381 property variant matrixData: Qt.point(Math.sin(angle), Math.cos(angle)) 382 383 anchors.fill: parent 384 385 vertexShader: " 386 attribute highp vec4 qt_Vertex; 387 attribute highp vec2 qt_MultiTexCoord0; 388 uniform highp mat4 qt_Matrix; 389 uniform highp vec2 matrixData; 390 uniform highp float horizontalRatio; 391 uniform highp float verticalRatio; 392 uniform highp vec2 center; 393 varying highp vec2 qt_TexCoord0; 394 varying highp vec2 qt_TexCoord1; 395 varying highp vec2 centerPoint; 396 397 void main() { 398 highp vec2 ratio = vec2(horizontalRatio, verticalRatio); 399 400 // Rotation matrix 401 highp mat2 rot = mat2(matrixData.y, -matrixData.x, 402 matrixData.x, matrixData.y); 403 404 qt_TexCoord0 = qt_MultiTexCoord0; 405 406 qt_TexCoord1 = qt_MultiTexCoord0; 407 qt_TexCoord1 -= center; 408 qt_TexCoord1 *= rot; 409 qt_TexCoord1 += center; 410 qt_TexCoord1 *= ratio; 411 412 centerPoint = center * ratio; 413 414 gl_Position = qt_Matrix * qt_Vertex; 415 } 416 " 417 418 fragmentShader: maskSource == undefined ? noMaskShader : maskShader 419 420 onFragmentShaderChanged: horizontalRatioChanged() 421 422 property string maskShader: " 423 uniform lowp sampler2D gradientImage; 424 uniform lowp sampler2D maskSource; 425 uniform lowp float qt_Opacity; 426 varying highp vec2 qt_TexCoord0; 427 varying highp vec2 qt_TexCoord1; 428 varying highp vec2 centerPoint; 429 430 void main() { 431 lowp vec4 gradientColor = texture2D(gradientImage, vec2(0.0, 2.0 * distance(qt_TexCoord1, centerPoint))); 432 lowp float maskAlpha = texture2D(maskSource, qt_TexCoord0).a; 433 gl_FragColor = gradientColor * maskAlpha * qt_Opacity; 434 } 435 " 436 437 property string noMaskShader: " 438 uniform lowp sampler2D gradientImage; 439 uniform lowp float qt_Opacity; 440 varying highp vec2 qt_TexCoord1; 441 varying highp vec2 centerPoint; 442 443 void main() { 444 lowp vec4 gradientColor = texture2D(gradientImage, vec2(0.0, 2.0 * distance(qt_TexCoord1, centerPoint))); 445 gl_FragColor = gradientColor * qt_Opacity; 446 } 447 " 448 } 449} 450