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 InnerShadow
45    \inqmlmodule QtGraphicalEffects
46    \since QtGraphicalEffects 1.0
47    \inherits QtQuick2::Item
48    \ingroup qtgraphicaleffects-drop-shadow
49    \brief Generates a colorized and blurred shadow inside the
50    source.
51
52    By default the effect produces a high quality shadow image, thus the
53    rendering speed of the shadow might not be the highest possible. The
54    rendering speed is reduced especially if the shadow edges are heavily
55    softened. For use cases that require faster rendering speed and for which
56    the highest possible visual quality is not necessary, property
57    \l{InnerShadow::fast}{fast} can be set to true.
58
59    \table
60    \header
61        \li Source
62        \li Effect applied
63    \row
64        \li \image Original_butterfly.png
65        \li \image InnerShadow_butterfly.png
66    \endtable
67
68    \note This effect is available when running with OpenGL.
69
70    \section1 Example
71
72    The following example shows how to apply the effect.
73    \snippet InnerShadow-example.qml example
74
75*/
76Item {
77    id: rootItem
78
79    /*!
80        This property defines the source item that is going to be used as the
81        source for the generated shadow.
82
83        \note It is not supported to let the effect include itself, for
84        instance by setting source to the effect's parent.
85    */
86    property variant source
87
88    /*!
89        Radius defines the softness of the shadow. A larger radius causes the
90        edges of the shadow to appear more blurry.
91
92        Depending on the radius value, value of the
93        \l{InnerShadow::samples}{samples} should be set to sufficiently large to
94        ensure the visual quality.
95
96        The value ranges from 0.0 (no blur) to inf. By default, the property is
97        set to \c 0.0 (no blur).
98
99        \table
100        \header
101        \li Output examples with different radius values
102        \li
103        \li
104        \row
105            \li \image InnerShadow_radius1.png
106            \li \image InnerShadow_radius2.png
107            \li \image InnerShadow_radius3.png
108        \row
109            \li \b { radius: 0 }
110            \li \b { radius: 6 }
111            \li \b { radius: 12 }
112        \row
113            \li \l samples: 24
114            \li \l samples: 24
115            \li \l samples: 24
116        \row
117            \li \l color: #000000
118            \li \l color: #000000
119            \li \l color: #000000
120        \row
121            \li \l horizontalOffset: 0
122            \li \l horizontalOffset: 0
123            \li \l horizontalOffset: 0
124        \row
125            \li \l verticalOffset: 0
126            \li \l verticalOffset: 0
127            \li \l verticalOffset: 0
128        \row
129            \li \l spread: 0
130            \li \l spread: 0
131            \li \l spread: 0
132        \endtable
133
134    */
135    property real radius: 0.0
136
137    /*!
138        This property defines how many samples are taken per pixel when edge
139        softening blur calculation is done. Larger value produces better
140        quality, but is slower to render.
141
142        Ideally, this value should be twice as large as the highest required
143        radius value, for example, if the radius is animated between 0.0 and
144        4.0, samples should be set to 8.
145
146        The value ranges from 0 to 32. By default, the property is set to \c 0.
147
148        This property is not intended to be animated. Changing this property may
149        cause the underlying OpenGL shaders to be recompiled.
150
151        When \l{InnerShadow::fast}{fast} property is set to true, this property
152        has no effect.
153
154    */
155    property int samples: 0
156
157    /*!
158        This property defines how large part of the shadow color is strengthened
159        near the source edges.
160
161        The value ranges from 0.0 to 1.0. By default, the property is set to \c
162        0.5.
163
164        \table
165        \header
166        \li Output examples with different spread values
167        \li
168        \li
169        \row
170            \li \image InnerShadow_spread1.png
171            \li \image InnerShadow_spread2.png
172            \li \image InnerShadow_spread3.png
173        \row
174            \li \b { spread: 0.0 }
175            \li \b { spread: 0.3 }
176            \li \b { spread: 0.5 }
177        \row
178            \li \l radius: 16
179            \li \l radius: 16
180            \li \l radius: 16
181        \row
182            \li \l samples: 24
183            \li \l samples: 24
184            \li \l samples: 24
185        \row
186            \li \l color: #000000
187            \li \l color: #000000
188            \li \l color: #000000
189        \row
190            \li \l horizontalOffset: 0
191            \li \l horizontalOffset: 0
192            \li \l horizontalOffset: 0
193        \row
194            \li \l verticalOffset: 0
195            \li \l verticalOffset: 0
196            \li \l verticalOffset: 0
197        \endtable
198
199    */
200    property real spread: 0.0
201
202    /*!
203        This property defines the RGBA color value which is used for the shadow.
204
205        By default, the property is set to \c "black".
206
207        \table
208        \header
209        \li Output examples with different color values
210        \li
211        \li
212        \row
213            \li \image InnerShadow_color1.png
214            \li \image InnerShadow_color2.png
215            \li \image InnerShadow_color3.png
216        \row
217            \li \b { color: #000000 }
218            \li \b { color: #ffffff }
219            \li \b { color: #ff0000 }
220        \row
221            \li \l radius: 16
222            \li \l radius: 16
223            \li \l radius: 16
224        \row
225            \li \l samples: 24
226            \li \l samples: 24
227            \li \l samples: 24
228        \row
229            \li \l horizontalOffset: 0
230            \li \l horizontalOffset: 0
231            \li \l horizontalOffset: 0
232        \row
233            \li \l verticalOffset: 0
234            \li \l verticalOffset: 0
235            \li \l verticalOffset: 0
236        \row
237            \li \l spread: 0.2
238            \li \l spread: 0.2
239            \li \l spread: 0.2
240        \endtable
241    */
242    property color color: "black"
243
244    /*!
245        \qmlproperty real QtGraphicalEffects::InnerShadow::horizontalOffset
246        \qmlproperty real QtGraphicalEffects::InnerShadow::verticalOffset
247
248        HorizontalOffset and verticalOffset properties define the offset for the
249        rendered shadow compared to the InnerShadow item position. Often, the
250        InnerShadow item is anchored so that it fills the source element. In
251        this case, if the HorizontalOffset and verticalOffset properties are set
252        to 0, the shadow is rendered fully inside the source item. By changing
253        the offset properties, the shadow can be positioned relatively to the
254        source item.
255
256        The values range from -inf to inf. By default, the properties are set to
257        \c 0.
258
259        \table
260        \header
261        \li Output examples with different horizontalOffset values
262        \li
263        \li
264        \row
265            \li \image InnerShadow_horizontalOffset1.png
266            \li \image InnerShadow_horizontalOffset2.png
267            \li \image InnerShadow_horizontalOffset3.png
268        \row
269            \li \b { horizontalOffset: -20 }
270            \li \b { horizontalOffset: 0 }
271            \li \b { horizontalOffset: 20 }
272        \row
273            \li \l radius: 16
274            \li \l radius: 16
275            \li \l radius: 16
276        \row
277            \li \l samples: 24
278            \li \l samples: 24
279            \li \l samples: 24
280        \row
281            \li \l color: #000000
282            \li \l color: #000000
283            \li \l color: #000000
284        \row
285            \li \l verticalOffset: 0
286            \li \l verticalOffset: 0
287            \li \l verticalOffset: 0
288        \row
289            \li \l spread: 0
290            \li \l spread: 0
291            \li \l spread: 0
292        \endtable
293
294    */
295    property real horizontalOffset: 0
296    property real verticalOffset: 0
297
298    /*!
299        This property selects the blurring algorithm that is used to produce the
300        softness for the effect. Setting this to true enables fast algorithm,
301        setting value to false produces higher quality result.
302
303        By default, the property is set to \c false.
304
305        \table
306        \header
307        \li Output examples with different fast values
308        \li
309        \li
310        \row
311            \li \image InnerShadow_fast1.png
312            \li \image InnerShadow_fast2.png
313        \row
314            \li \b { fast: false }
315            \li \b { fast: true }
316        \row
317            \li \l radius: 16
318            \li \l radius: 16
319        \row
320            \li \l samples: 24
321            \li \l samples: 24
322        \row
323            \li \l color: #000000
324            \li \l color: #000000
325        \row
326            \li \l horizontalOffset: 0
327            \li \l horizontalOffset: 0
328        \row
329            \li \l verticalOffset: 0
330            \li \l verticalOffset: 0
331        \row
332            \li \l spread: 0.2
333            \li \l spread: 0.2
334        \endtable
335    */
336    property bool fast: false
337
338    /*!
339        This property allows the effect output pixels to be cached in order to
340        improve the rendering performance. Every time the source or effect
341        properties are changed, the pixels in the cache must be updated. Memory
342        consumption is increased, because an extra buffer of memory is required
343        for storing the effect output.
344
345        It is recommended to disable the cache when the source or the effect
346        properties are animated.
347
348        By default, the property is set to \c false.
349
350    */
351    property bool cached: false
352
353    Loader {
354        anchors.fill: parent
355        sourceComponent: rootItem.fast ? innerShadow : gaussianInnerShadow
356    }
357
358    Component {
359        id: gaussianInnerShadow
360        GaussianInnerShadow {
361            anchors.fill: parent
362            source: rootItem.source
363            radius: rootItem.radius
364            maximumRadius: rootItem.samples * 0.5
365            color: rootItem.color
366            cached: rootItem.cached
367            spread: rootItem.spread
368            horizontalOffset: rootItem.horizontalOffset
369            verticalOffset: rootItem.verticalOffset
370        }
371    }
372
373    Component {
374        id: innerShadow
375        FastInnerShadow {
376            anchors.fill: parent
377            source: rootItem.source
378            blur: Math.pow(rootItem.radius / 64.0, 0.4)
379            color: rootItem.color
380            cached: rootItem.cached
381            spread: rootItem.spread
382            horizontalOffset: rootItem.horizontalOffset
383            verticalOffset: rootItem.verticalOffset
384        }
385    }
386}
387