1/****************************************************************************
2**
3** Copyright (C) 2017 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:LGPL$
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** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40import QtQuick 2.12
41import QtGraphicalEffects.private 1.12
42
43/*!
44    \qmltype RadialGradient
45    \inqmlmodule QtGraphicalEffects
46    \since QtGraphicalEffects 1.0
47    \inherits QtQuick2::Item
48    \ingroup qtgraphicaleffects-gradient
49    \brief Draws a radial gradient.
50
51    A gradient is defined by two or more colors, which are blended seamlessly.
52    The colors start from the middle of the item and end at the borders.
53
54    \table
55    \header
56        \li Effect applied
57    \row
58        \li \image RadialGradient.png
59    \endtable
60
61    \note This effect is available when running with OpenGL.
62
63    \section1 Example
64
65    The following example shows how to apply the effect.
66    \snippet RadialGradient-example.qml example
67
68*/
69Item {
70    id: rootItem
71
72    /*!
73        This property allows the effect output pixels to be cached in order to
74        improve the rendering performance.
75
76        Every time the source or effect properties are changed, the pixels in
77        the cache must be updated. Memory consumption is increased, because an
78        extra buffer of memory is required for storing the effect output.
79
80        It is recommended to disable the cache when the source or the effect
81        properties are animated.
82
83        By default, the property is set to \c false.
84    */
85    property bool cached: false
86
87    /*!
88        \qmlproperty real RadialGradient::horizontalOffset
89        \qmlproperty real RadialGradient::verticalOffset
90
91        The horizontalOffset and verticalOffset properties define the offset in
92        pixels for the center point of the gradient compared to the item center.
93
94        The values range from -inf to inf. By default, these properties are set
95        to \c 0.
96
97        \table
98        \header
99        \li Output examples with different horizontalOffset values
100        \li
101        \li
102        \row
103            \li \image RadialGradient_horizontalOffset1.png
104            \li \image RadialGradient_horizontalOffset2.png
105            \li \image RadialGradient_horizontalOffset3.png
106        \row
107            \li \b { horizontalOffset: -150 }
108            \li \b { horizontalOffset: 0 }
109            \li \b { horizontalOffset: 150 }
110        \row
111            \li \l verticalOffset: 0
112            \li \l verticalOffset: 0
113            \li \l verticalOffset: 0
114        \row
115            \li \l horizontalRadius: 300
116            \li \l horizontalRadius: 300
117            \li \l horizontalRadius: 300
118        \row
119            \li \l verticalRadius: 300
120            \li \l verticalRadius: 300
121            \li \l verticalRadius: 300
122        \row
123            \li \l angle: 0
124            \li \l angle: 0
125            \li \l angle: 0
126        \endtable
127
128    */
129    property real horizontalOffset: 0.0
130    property real verticalOffset: 0.0
131
132    /*!
133        \qmlproperty real RadialGradient::horizontalRadius
134        \qmlproperty real RadialGradient::verticalRadius
135
136        The horizontalRadius and verticalRadius properties define the shape and
137        size of the radial gradient. If the radiuses are equal, the shape of the
138        gradient is a circle. If the horizontal and vertical radiuses differ,
139        the shape is elliptical. The radiuses are given in pixels.
140
141        The value ranges from -inf to inf. By default, horizontalRadius is bound
142        to width and verticalRadius is bound to height.
143
144        \table
145        \header
146        \li Output examples with different horizontalRadius values
147        \li
148        \li
149        \row
150            \li \image RadialGradient_horizontalRadius1.png
151            \li \image RadialGradient_horizontalRadius2.png
152        \row
153            \li \b { horizontalRadius: 300 }
154            \li \b { horizontalRadius: 100 }
155        \row
156            \li \l horizontalOffset: 0
157            \li \l horizontalOffset: 0
158        \row
159            \li \l verticalOffset: 0
160            \li \l verticalOffset: 0
161        \row
162            \li \l verticalRadius: 300
163            \li \l verticalRadius: 300
164        \row
165            \li \l angle: 0
166            \li \l angle: 0
167        \row
168            \li \l gradient: QQuickGradient(0xa05fb10)
169            \li \l gradient: QQuickGradient(0xa05fb10)
170        \endtable
171
172    */
173    property real horizontalRadius: width
174    property real verticalRadius: height
175
176    /*!
177        This property defines the rotation of the gradient around its center
178        point. The rotation is only visible when the
179        \l{RadialGradient::horizontalRadius}{horizontalRadius} and
180        \l{RadialGradient::verticalRadius}{verticalRadius} properties are not
181        equal. The angle is given in degrees and the default value is \c 0.
182
183        \table
184        \header
185        \li Output examples with different angle values
186        \li
187        \li
188        \row
189            \li \image RadialGradient_angle1.png
190            \li \image RadialGradient_angle2.png
191            \li \image RadialGradient_angle3.png
192        \row
193            \li \b { angle: 0 }
194            \li \b { angle: 45 }
195            \li \b { angle: 90 }
196        \row
197            \li \l horizontalOffset: 0
198            \li \l horizontalOffset: 0
199            \li \l horizontalOffset: 0
200        \row
201            \li \l verticalOffset: 0
202            \li \l verticalOffset: 0
203            \li \l verticalOffset: 0
204        \row
205            \li \l horizontalRadius: 100
206            \li \l horizontalRadius: 100
207            \li \l horizontalRadius: 100
208        \row
209            \li \l verticalRadius: 300
210            \li \l verticalRadius: 300
211            \li \l verticalRadius: 300
212        \endtable
213    */
214    property real angle: 0.0
215
216    /*!
217        This property defines the item that is going to be filled with gradient.
218        Source item gets rendered into an intermediate pixel buffer and the
219        alpha values from the result are used to determine the gradient's pixels
220        visibility in the display. The default value for source is undefined and
221        in that case whole effect area is filled with gradient.
222
223        \table
224        \header
225        \li Output examples with different source values
226        \li
227        \li
228        \row
229            \li \image RadialGradient_maskSource1.png
230            \li \image RadialGradient_maskSource2.png
231        \row
232            \li \b { source: undefined }
233            \li \b { source: Image { source: images/butterfly.png } }
234        \row
235            \li \l horizontalOffset: 0
236            \li \l horizontalOffset: 0
237        \row
238            \li \l verticalOffset: 0
239            \li \l verticalOffset: 0
240        \row
241            \li \l horizontalRadius: 300
242            \li \l horizontalRadius: 300
243        \row
244            \li \l verticalRadius: 300
245            \li \l verticalRadius: 300
246        \row
247            \li \l angle: 0
248            \li \l angle: 0
249        \endtable
250
251        \note It is not supported to let the effect include itself, for
252        instance by setting source to the effect's parent.
253    */
254    property variant source
255
256    /*!
257        A gradient is defined by two or more colors, which are blended
258        seamlessly. The colors are specified as a set of GradientStop child
259        items, each of which defines a position on the gradient from 0.0 to 1.0
260        and a color. The position of each GradientStop is defined by setting the
261        position property. The color is defined by setting the color property.
262
263        \table
264        \header
265        \li Output examples with different gradient values
266        \li
267        \li
268        \row
269            \li \image RadialGradient_gradient1.png
270            \li \image RadialGradient_gradient2.png
271            \li \image RadialGradient_gradient3.png
272        \row
273            \li \b {gradient:} \code
274    Gradient {
275      GradientStop {
276       position: 0.000
277       color: Qt.rgba(1, 0, 0, 1)
278      }
279      GradientStop {
280       position: 0.167
281       color: Qt.rgba(1, 1, 0, 1)
282      }
283      GradientStop {
284       position: 0.333
285       color: Qt.rgba(0, 1, 0, 1)
286      }
287      GradientStop {
288       position: 0.500
289       color: Qt.rgba(0, 1, 1, 1)
290       }
291      GradientStop {
292       position: 0.667
293       color: Qt.rgba(0, 0, 1, 1)
294      }
295      GradientStop {
296       position: 0.833
297       color: Qt.rgba(1, 0, 1, 1)
298      }
299      GradientStop {
300       position: 1.000
301       color: Qt.rgba(1, 0, 0, 1)
302      }
303    }
304        \endcode
305            \li \b {gradient:} \code
306    Gradient {
307      GradientStop {
308        position: 0.0
309        color: "#F0F0F0"
310      }
311      GradientStop {
312        position: 0.5
313        color: "#000000"
314      }
315      GradientStop {
316        position: 1.0
317        color: "#F0F0F0"
318      }
319    }
320        \endcode
321            \li \b {gradient:}
322    \code
323    Gradient {
324      GradientStop {
325        position: 0.0
326        color: "#00000000"
327      }
328      GradientStop {
329        position: 1.0
330        color: "#FF000000"
331      }
332    }
333    \endcode
334        \row
335            \li \l horizontalOffset: 0
336            \li \l horizontalOffset: 0
337            \li \l horizontalOffset: 0
338        \row
339            \li \l verticalOffset: 0
340            \li \l verticalOffset: 0
341            \li \l verticalOffset: 0
342        \row
343            \li \l horizontalRadius: 300
344            \li \l horizontalRadius: 300
345            \li \l horizontalRadius: 300
346        \row
347            \li \l verticalRadius: 300
348            \li \l verticalRadius: 300
349            \li \l verticalRadius: 300
350        \row
351            \li \l angle: 0
352            \li \l angle: 0
353            \li \l angle: 0
354        \endtable
355    */
356    property Gradient gradient: Gradient {
357        GradientStop { position: 0.0; color: "white" }
358        GradientStop { position: 1.0; color: "black" }
359    }
360
361    SourceProxy {
362        id: maskSourceProxy
363        input: rootItem.source
364    }
365
366    ShaderEffectSource {
367        id: gradientSource
368        sourceItem: Rectangle {
369            width: 16
370            height: 256
371            gradient: rootItem.gradient
372            smooth: true
373        }
374        smooth: true
375        hideSource: true
376        visible: false
377    }
378
379   ShaderEffectSource {
380        id: cacheItem
381        anchors.fill: parent
382        visible: rootItem.cached
383        smooth: true
384        sourceItem: shaderItem
385        live: true
386        hideSource: visible
387    }
388
389    ShaderEffect {
390        id: shaderItem
391        property variant gradientImage: gradientSource
392        property variant maskSource: maskSourceProxy.output
393        property variant center: Qt.point(0.5 + rootItem.horizontalOffset / width, 0.5 + rootItem.verticalOffset / height)
394        property real horizontalRatio: rootItem.horizontalRadius > 0 ? width / (2 * rootItem.horizontalRadius) : width * 16384
395        property real verticalRatio: rootItem.verticalRadius > 0 ? height / (2 * rootItem.verticalRadius) : height * 16384
396        property real angle: -rootItem.angle / 360 * 2 * Math.PI
397        property variant matrixData: Qt.point(Math.sin(angle), Math.cos(angle))
398
399        anchors.fill: parent
400
401        vertexShader: "qrc:/qt-project.org/imports/QtGraphicalEffects/shaders/radialgradient.vert"
402
403        fragmentShader: maskSource == undefined ? noMaskShader : maskShader
404
405        onFragmentShaderChanged: horizontalRatioChanged()
406
407        property string maskShader: "qrc:/qt-project.org/imports/QtGraphicalEffects/shaders/radialgradient_mask.frag"
408        property string noMaskShader: "qrc:/qt-project.org/imports/QtGraphicalEffects/shaders/radialgradient_nomask.frag"
409    }
410}
411