Document recursion limitations of the graphical effects.
[qt:qtgraphicaleffects.git] / src / effects / LinearGradient.qml
1 /****************************************************************************
2 **
3 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the Qt Graphical Effects module.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
10 **
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
13 ** met:
14 **   * Redistributions of source code must retain the above copyright
15 **     notice, this list of conditions and the following disclaimer.
16 **   * Redistributions in binary form must reproduce the above copyright
17 **     notice, this list of conditions and the following disclaimer in
18 **     the documentation and/or other materials provided with the
19 **     distribution.
20 **   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
21 **     of its contributors may be used to endorse or promote products derived
22 **     from this software without specific prior written permission.
23 **
24 **
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40
41 import QtQuick 2.0
42 import "private"
43
44 /*!
45     \qmltype LinearGradient
46     \inqmlmodule QtGraphicalEffects 1.0
47     \since QtGraphicalEffects 1.0
48     \inherits QtQuick2::Item
49     \ingroup qtgraphicaleffects-gradient
50     \brief Draws a linear gradient.
51
52     A gradient is defined by two or more colors, which are blended seamlessly.
53     The colors start from the given start point and end to the given end point.
54
55     \table
56     \header
57         \li Effect applied
58     \row
59         \li \image LinearGradient.png
60     \endtable
61
62     \section1 Example
63
64     The following example shows how to apply the effect.
65     \snippet LinearGradient-example.qml example
66
67 */
68 Item {
69     id: rootItem
70
71     /*!
72         This property defines the starting point where the color at gradient
73         position of 0.0 is rendered. Colors at larger position values are
74         rendered linearly towards the end point. The point is given in pixels
75         and the default value is Qt.point(0, 0). Setting the default values for
76         the start and \l{LinearGradient::end}{end} results in a full height
77         linear gradient on the y-axis.
78
79         \table
80         \header
81         \li Output examples with different start values
82         \li
83         \li
84         \row
85             \li \image LinearGradient_start1.png
86             \li \image LinearGradient_start2.png
87             \li \image LinearGradient_start3.png
88         \row
89             \li \b { start: QPoint(0, 0) }
90             \li \b { start: QPoint(150, 150) }
91             \li \b { start: QPoint(300, 0) }
92         \row
93             \li \l end: QPoint(300, 300)
94             \li \l end: QPoint(300, 300)
95             \li \l end: QPoint(300, 300)
96         \endtable
97
98     */
99     property variant start: Qt.point(0, 0)
100
101     /*!
102         This property defines the ending point where the color at gradient
103         position of 1.0 is rendered. Colors at smaller position values are
104         rendered linearly towards the start point. The point is given in pixels
105         and the default value is Qt.point(0, height). Setting the default values
106         for the \l{LinearGradient::start}{start} and end results in a full
107         height linear gradient on the y-axis.
108
109         \table
110         \header
111         \li Output examples with different end values
112         \li
113         \li
114         \row
115             \li \image LinearGradient_end1.png
116             \li \image LinearGradient_end2.png
117             \li \image LinearGradient_end3.png
118         \row
119             \li \b { end: Qt.point(300, 300) }
120             \li \b { end: Qt.point(150, 150) }
121             \li \b { end: Qt.point(300, 0) }
122         \row
123             \li \l start: Qt.point(0, 0)
124             \li \l start: Qt.point(0, 0)
125             \li \l start: Qt.point(0, 0)
126         \endtable
127
128     */
129     property variant end: Qt.point(0, height)
130
131     /*!
132         This property allows the effect output pixels to be cached in order to
133         improve the rendering performance.
134
135         Every time the source or effect properties are changed, the pixels in
136         the cache must be updated. Memory consumption is increased, because an
137         extra buffer of memory is required for storing the effect output.
138
139         It is recommended to disable the cache when the source or the effect
140         properties are animated.
141
142         By default, the property is set to \c false.
143     */
144     property bool cached: false
145
146     /*!
147         This property defines the item that is going to be filled with gradient.
148         Source item gets rendered into an intermediate pixel buffer and the
149         alpha values from the result are used to determine the gradient's pixels
150         visibility in the display. The default value for source is undefined and
151         in that case whole effect area is filled with gradient.
152
153         \table
154         \header
155         \li Output examples with different source values
156         \li
157         \li
158         \row
159             \li \image LinearGradient_maskSource1.png
160             \li \image LinearGradient_maskSource2.png
161         \row
162             \li \b { source: undefined }
163             \li \b { source: Image { source: images/butterfly.png } }
164         \row
165             \li \l start: Qt.point(0, 0)
166             \li \l start: Qt.point(0, 0)
167         \row
168             \li \l end: Qt.point(300, 300)
169             \li \l end: Qt.point(300, 300)
170         \endtable
171
172         \note It is not supported to let the effect include itself, for
173         instance by setting source to the effect's parent.
174     */
175     property variant source
176
177
178     /*!
179         A gradient is defined by two or more colors, which are blended
180         seamlessly. The colors are specified as a set of GradientStop child
181         items, each of which defines a position on the gradient from 0.0 to 1.0
182         and a color. The position of each GradientStop is defined by the
183         position property, and the color is definded by the color property.
184
185         \table
186         \header
187         \li Output examples with different gradient values
188         \li
189         \li
190         \row
191             \li \image LinearGradient_gradient1.png
192             \li \image LinearGradient_gradient2.png
193             \li \image LinearGradient_gradient3.png
194             \row
195             \li \b {gradient:} \code
196     Gradient {
197       GradientStop { position: 0.000
198       color: Qt.rgba(1, 0, 0, 1) }
199       GradientStop { position: 0.167;
200       color: Qt.rgba(1, 1, 0, 1) }
201       GradientStop { position: 0.333;
202       color: Qt.rgba(0, 1, 0, 1) }
203       GradientStop { position: 0.500;
204       color: Qt.rgba(0, 1, 1, 1) }
205       GradientStop { position: 0.667;
206       color: Qt.rgba(0, 0, 1, 1) }
207       GradientStop { position: 0.833;
208       color: Qt.rgba(1, 0, 1, 1) }
209       GradientStop { position: 1.000;
210       color: Qt.rgba(1, 0, 0, 1) }
211     }
212         \endcode
213             \li \b {gradient:} \code
214     Gradient {
215       GradientStop { position: 0.0
216       color: "#F0F0F0"
217       }
218       GradientStop { position: 0.5
219       color: "#000000"
220       }
221       GradientStop { position: 1.0
222       color: "#F0F0F0"
223       }
224     }
225         \endcode
226             \li \b {gradient:} \code
227     Gradient {
228       GradientStop { position: 0.0
229         color: "#00000000"
230       }
231       GradientStop { position: 1.0
232         color: "#FF000000"
233       }
234     }
235         \endcode
236         \row
237             \li \l start: Qt.point(0, 0)
238             \li \l start: Qt.point(0, 0)
239             \li \l start: Qt.point(0, 0)
240         \row
241             \li \l end: Qt.point(300, 300)
242             \li \l end: Qt.point(300, 300)
243             \li \l end: Qt.point(300, 300)
244         \endtable
245
246     */
247     property Gradient gradient: Gradient {
248         GradientStop { position: 0.0; color: "white" }
249         GradientStop { position: 1.0; color: "black" }
250     }
251
252     SourceProxy {
253         id: maskSourceProxy
254         input: rootItem.source
255     }
256
257     ShaderEffectSource {
258         id: gradientSource
259         sourceItem: Rectangle {
260             width: 16
261             height: 256
262             gradient: rootItem.gradient
263             smooth: true
264         }
265         smooth: true
266         hideSource: true
267         visible: false
268     }
269
270    ShaderEffectSource {
271         id: cacheItem
272         anchors.fill: parent
273         visible: rootItem.cached
274         smooth: true
275         sourceItem: shaderItem
276         live: true
277         hideSource: visible
278     }
279
280     ShaderEffect {
281         id: shaderItem
282
283         anchors.fill: parent
284
285         property variant source: gradientSource
286         property variant maskSource: maskSourceProxy.output
287         property variant startPoint: Qt.point(start.x / width, start.y / height)
288         property real dx: end.x - start.x
289         property real dy: end.y - start.y
290         property real l: 1.0 / Math.sqrt(Math.pow(dx / width, 2.0) + Math.pow(dy / height, 2.0))
291         property real angle: Math.atan2(dx, dy)
292         property variant matrixData: Qt.point(Math.sin(angle), Math.cos(angle))
293
294         vertexShader: "
295             attribute highp vec4 qt_Vertex;
296             attribute highp vec2 qt_MultiTexCoord0;
297             uniform highp mat4 qt_Matrix;
298             varying highp vec2 qt_TexCoord0;
299             varying highp vec2 qt_TexCoord1;
300             uniform highp vec2 startPoint;
301             uniform highp float l;
302             uniform highp vec2 matrixData;
303
304             void main() {
305                 highp mat2 rot = mat2(matrixData.y, -matrixData.x,
306                                       matrixData.x,  matrixData.y);
307
308                 qt_TexCoord0 = qt_MultiTexCoord0;
309
310                 qt_TexCoord1 = qt_MultiTexCoord0 * l;
311                 qt_TexCoord1 -= startPoint * l;
312                 qt_TexCoord1 *= rot;
313
314                 gl_Position = qt_Matrix * qt_Vertex;
315             }
316         "
317
318         fragmentShader: maskSource == undefined ? noMaskShader : maskShader
319
320         onFragmentShaderChanged: lChanged()
321
322         property string maskShader: "
323             uniform lowp sampler2D source;
324             uniform lowp sampler2D maskSource;
325             uniform lowp float qt_Opacity;
326             varying highp vec2 qt_TexCoord0;
327             varying highp vec2 qt_TexCoord1;
328
329             void main() {
330                 lowp vec4 gradientColor = texture2D(source, qt_TexCoord1);
331                 lowp float maskAlpha = texture2D(maskSource, qt_TexCoord0).a;
332                 gl_FragColor = gradientColor * maskAlpha * qt_Opacity;
333             }
334         "
335
336         property string noMaskShader: "
337             uniform lowp sampler2D source;
338             uniform lowp float qt_Opacity;
339             varying highp vec2 qt_TexCoord1;
340
341             void main() {
342                 gl_FragColor = texture2D(source, qt_TexCoord1) * qt_Opacity;
343             }
344         "
345     }
346 }