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 LinearGradient
45    \inqmlmodule QtGraphicalEffects
46    \since QtGraphicalEffects 1.0
47    \inherits QtQuick2::Item
48    \ingroup qtgraphicaleffects-gradient
49    \brief Draws a linear gradient.
50
51    A gradient is defined by two or more colors, which are blended seamlessly.
52    The colors start from the given start point and end to the given end point.
53
54    \table
55    \header
56        \li Effect applied
57    \row
58        \li \image LinearGradient.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 LinearGradient-example.qml example
67
68*/
69Item {
70    id: rootItem
71
72    /*!
73        This property defines the starting point where the color at gradient
74        position of 0.0 is rendered. Colors at larger position values are
75        rendered linearly towards the end point. The point is given in pixels
76        and the default value is Qt.point(0, 0). Setting the default values for
77        the start and \l{LinearGradient::end}{end} results in a full height
78        linear gradient on the y-axis.
79
80        \table
81        \header
82        \li Output examples with different start values
83        \li
84        \li
85        \row
86            \li \image LinearGradient_start1.png
87            \li \image LinearGradient_start2.png
88            \li \image LinearGradient_start3.png
89        \row
90            \li \b { start: QPoint(0, 0) }
91            \li \b { start: QPoint(150, 150) }
92            \li \b { start: QPoint(300, 0) }
93        \row
94            \li \l end: QPoint(300, 300)
95            \li \l end: QPoint(300, 300)
96            \li \l end: QPoint(300, 300)
97        \endtable
98
99    */
100    property variant start: Qt.point(0, 0)
101
102    /*!
103        This property defines the ending point where the color at gradient
104        position of 1.0 is rendered. Colors at smaller position values are
105        rendered linearly towards the start point. The point is given in pixels
106        and the default value is Qt.point(0, height). Setting the default values
107        for the \l{LinearGradient::start}{start} and end results in a full
108        height linear gradient on the y-axis.
109
110        \table
111        \header
112        \li Output examples with different end values
113        \li
114        \li
115        \row
116            \li \image LinearGradient_end1.png
117            \li \image LinearGradient_end2.png
118            \li \image LinearGradient_end3.png
119        \row
120            \li \b { end: Qt.point(300, 300) }
121            \li \b { end: Qt.point(150, 150) }
122            \li \b { end: Qt.point(300, 0) }
123        \row
124            \li \l start: Qt.point(0, 0)
125            \li \l start: Qt.point(0, 0)
126            \li \l start: Qt.point(0, 0)
127        \endtable
128
129    */
130    property variant end: Qt.point(0, height)
131
132    /*!
133        This property allows the effect output pixels to be cached in order to
134        improve the rendering performance.
135
136        Every time the source or effect properties are changed, the pixels in
137        the cache must be updated. Memory consumption is increased, because an
138        extra buffer of memory is required for storing the effect output.
139
140        It is recommended to disable the cache when the source or the effect
141        properties are animated.
142
143        By default, the property is set to \c false.
144    */
145    property bool cached: false
146
147    /*!
148        This property defines the item that is going to be filled with gradient.
149        Source item gets rendered into an intermediate pixel buffer and the
150        alpha values from the result are used to determine the gradient's pixels
151        visibility in the display. The default value for source is undefined and
152        in that case whole effect area is filled with gradient.
153
154        \table
155        \header
156        \li Output examples with different source values
157        \li
158        \li
159        \row
160            \li \image LinearGradient_maskSource1.png
161            \li \image LinearGradient_maskSource2.png
162        \row
163            \li \b { source: undefined }
164            \li \b { source: Image { source: images/butterfly.png } }
165        \row
166            \li \l start: Qt.point(0, 0)
167            \li \l start: Qt.point(0, 0)
168        \row
169            \li \l end: Qt.point(300, 300)
170            \li \l end: Qt.point(300, 300)
171        \endtable
172
173        \note It is not supported to let the effect include itself, for
174        instance by setting source to the effect's parent.
175    */
176    property variant source
177
178
179    /*!
180        A gradient is defined by two or more colors, which are blended
181        seamlessly. The colors are specified as a set of GradientStop child
182        items, each of which defines a position on the gradient from 0.0 to 1.0
183        and a color. The position of each GradientStop is defined by the
184        position property, and the color is definded by the color property.
185
186        \table
187        \header
188        \li Output examples with different gradient values
189        \li
190        \li
191        \row
192            \li \image LinearGradient_gradient1.png
193            \li \image LinearGradient_gradient2.png
194            \li \image LinearGradient_gradient3.png
195            \row
196            \li \b {gradient:} \code
197    Gradient {
198      GradientStop {
199         position: 0.000
200         color: Qt.rgba(1, 0, 0, 1)
201      }
202      GradientStop {
203         position: 0.167
204         color: Qt.rgba(1, 1, 0, 1)
205      }
206      GradientStop {
207         position: 0.333
208         color: Qt.rgba(0, 1, 0, 1)
209      }
210      GradientStop {
211         position: 0.500
212         color: Qt.rgba(0, 1, 1, 1)
213      }
214      GradientStop {
215         position: 0.667
216         color: Qt.rgba(0, 0, 1, 1)
217      }
218      GradientStop {
219         position: 0.833
220         color: Qt.rgba(1, 0, 1, 1)
221      }
222      GradientStop {
223         position: 1.000
224         color: Qt.rgba(1, 0, 0, 1)
225      }
226    }
227        \endcode
228            \li \b {gradient:} \code
229    Gradient {
230      GradientStop {
231        position: 0.0
232        color: "#F0F0F0"
233      }
234      GradientStop {
235        position: 0.5
236        color: "#000000"
237      }
238      GradientStop {
239        position: 1.0
240        color: "#F0F0F0"
241      }
242    }
243        \endcode
244            \li \b {gradient:} \code
245    Gradient {
246      GradientStop {
247        position: 0.0
248        color: "#00000000"
249      }
250      GradientStop {
251        position: 1.0
252        color: "#FF000000"
253      }
254    }
255        \endcode
256        \row
257            \li \l start: Qt.point(0, 0)
258            \li \l start: Qt.point(0, 0)
259            \li \l start: Qt.point(0, 0)
260        \row
261            \li \l end: Qt.point(300, 300)
262            \li \l end: Qt.point(300, 300)
263            \li \l end: Qt.point(300, 300)
264        \endtable
265
266    */
267    property Gradient gradient: Gradient {
268        GradientStop { position: 0.0; color: "white" }
269        GradientStop { position: 1.0; color: "black" }
270    }
271
272    SourceProxy {
273        id: maskSourceProxy
274        input: rootItem.source
275    }
276
277    ShaderEffectSource {
278        id: gradientSource
279        sourceItem: Rectangle {
280            width: 16
281            height: 256
282            gradient: rootItem.gradient
283            smooth: true
284        }
285        smooth: true
286        hideSource: true
287        visible: false
288    }
289
290   ShaderEffectSource {
291        id: cacheItem
292        anchors.fill: parent
293        visible: rootItem.cached
294        smooth: true
295        sourceItem: shaderItem
296        live: true
297        hideSource: visible
298    }
299
300    ShaderEffect {
301        id: shaderItem
302
303        anchors.fill: parent
304
305        property variant source: gradientSource
306        property variant maskSource: maskSourceProxy.output
307        property variant startPoint: Qt.point(start.x / width, start.y / height)
308        property real dx: end.x - start.x
309        property real dy: end.y - start.y
310        property real l: 1.0 / Math.sqrt(Math.pow(dx / width, 2.0) + Math.pow(dy / height, 2.0))
311        property real angle: Math.atan2(dx, dy)
312        property variant matrixData: Qt.point(Math.sin(angle), Math.cos(angle))
313
314        vertexShader: "qrc:/qt-project.org/imports/QtGraphicalEffects/shaders/lineargradient.vert"
315
316        fragmentShader: maskSource == undefined ? noMaskShader : maskShader
317
318        onFragmentShaderChanged: lChanged()
319
320        property string maskShader: "qrc:/qt-project.org/imports/QtGraphicalEffects/shaders/lineargradient_mask.frag"
321        property string noMaskShader: "qrc:/qt-project.org/imports/QtGraphicalEffects/shaders/lineargradient_nomask.frag"
322    }
323}
324