5#include <private/qquickrectangularshadow_p_p.h>
6#include <private/qquickshadereffect_p.h>
7#include <private/qquickitem_p.h>
8#include <QtCore/qurl.h>
9#include <QtGui/qvector4d.h>
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
144
145
146
147
148
149
150
151
153QQuickRectangularShadow::QQuickRectangularShadow(QQuickItem *parent)
154 : QQuickItem(*
new QQuickRectangularShadowPrivate, parent)
156 setFlag(ItemHasContents);
160
161
162
163
164
165
166
167
168QVector2D QQuickRectangularShadow::offset()
const
170 Q_D(
const QQuickRectangularShadow);
174void QQuickRectangularShadow::setOffset(
const QVector2D &offset)
176 Q_D(QQuickRectangularShadow);
177 if (offset == d->m_offset)
180 d->m_offset = offset;
181 d->updateSizeProperties();
183 Q_EMIT offsetChanged();
187
188
189
190
191
192
193QColor QQuickRectangularShadow::color()
const
195 Q_D(
const QQuickRectangularShadow);
199void QQuickRectangularShadow::setColor(
const QColor &color)
201 Q_D(QQuickRectangularShadow);
202 if (color == d->m_color)
208 Q_EMIT colorChanged();
212
213
214
215
216
217
218
219
220
221
222
223qreal QQuickRectangularShadow::blur()
const
225 Q_D(
const QQuickRectangularShadow);
229void QQuickRectangularShadow::setBlur(qreal blur)
231 Q_D(QQuickRectangularShadow);
232 blur = qMax(qreal(0), blur);
233 if (blur == d->m_blur)
237 d->updateSizeProperties();
239 Q_EMIT blurChanged();
243
244
245
246
247
248
249
250
251
252
253qreal QQuickRectangularShadow::radius()
const
255 Q_D(
const QQuickRectangularShadow);
259void QQuickRectangularShadow::setRadius(qreal radius)
261 Q_D(QQuickRectangularShadow);
262 radius = qMax(qreal(0), radius);
263 if (radius == d->m_radius)
266 d->m_radius = radius;
267 d->updateSizeProperties();
269 Q_EMIT radiusChanged();
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290qreal QQuickRectangularShadow::spread()
const
292 Q_D(
const QQuickRectangularShadow);
296void QQuickRectangularShadow::setSpread(qreal spread)
298 Q_D(QQuickRectangularShadow);
299 if (spread == d->m_spread)
302 d->m_spread = spread;
303 d->updateSizeProperties();
305 Q_EMIT spreadChanged();
309
310
311
312
313
314
315
316
317
318
319
320
321
322bool QQuickRectangularShadow::isCached()
const
324 Q_D(
const QQuickRectangularShadow);
328void QQuickRectangularShadow::setCached(
bool cached)
330 Q_D(QQuickRectangularShadow);
331 if (cached == d->m_cached)
334 d->m_cached = cached;
337 Q_EMIT cachedChanged();
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392QQuickItem *QQuickRectangularShadow::material()
const
394 Q_D(
const QQuickRectangularShadow);
395 return d->currentMaterial();
398void QQuickRectangularShadow::setMaterial(QQuickItem *item)
400 Q_D(QQuickRectangularShadow);
401 if (item == d->m_material)
405 item->setParentItem(
this);
409 d->m_material->setVisible(
false);
411 d->m_material = item;
412 d->updateShaderSource();
414 Q_EMIT materialChanged();
419void QQuickRectangularShadow::componentComplete()
421 Q_D(QQuickRectangularShadow);
422 QQuickItem::componentComplete();
426void QQuickRectangularShadow::geometryChange(
const QRectF &newGeometry,
const QRectF &oldGeometry)
428 Q_D(QQuickRectangularShadow);
429 QQuickItem::geometryChange(newGeometry, oldGeometry);
430 if (width() > 0 && height() > 0)
431 d->handleGeometryChange(newGeometry, oldGeometry);
434void QQuickRectangularShadow::itemChange(ItemChange change,
const ItemChangeData &value)
436 Q_D(QQuickRectangularShadow);
437 d->handleItemChange(change, value);
438 QQuickItem::itemChange(change, value);
443QQuickRectangularShadowPrivate::QQuickRectangularShadowPrivate()
445 Q_Q(QQuickRectangularShadow);
446 m_defaultMaterial =
new QQuickShaderEffect(q);
449 m_defaultMaterial->setProperty(
"iResolution", QVector3D());
450 m_defaultMaterial->setProperty(
"rectSize", QPointF());
451 m_defaultMaterial->setProperty(
"color", QColorConstants::Black);
452 m_defaultMaterial->setProperty(
"radius", 0.0);
453 m_defaultMaterial->setProperty(
"blur", 10.0);
456void QQuickRectangularShadowPrivate::initialize()
458 Q_Q(QQuickRectangularShadow);
461 if (!q->isComponentComplete())
465 if (q->width() <= 0 || q->height() <= 0)
468 m_defaultMaterial->setParentItem(q);
469 m_defaultMaterial->setZ(-1);
471 setImplicitAntialiasing(
true);
473 QUrl fs = QUrl(QStringLiteral(
"qrc:/data/shaders/rectangularshadow.frag.qsb"));
474 m_defaultMaterial->setFragmentShader(fs);
475 QUrl vs = QUrl(QStringLiteral(
"qrc:/data/shaders/rectangularshadow.vert.qsb"));
476 m_defaultMaterial->setVertexShader(vs);
478 updateShaderSource();
479 m_initialized =
true;
482void QQuickRectangularShadowPrivate::handleItemChange(QQuickItem::ItemChange change,
const QQuickItem::ItemChangeData &value)
485 if (change == QQuickItem::ItemSceneChange)
489void QQuickRectangularShadowPrivate::handleGeometryChange(
const QRectF &newGeometry,
const QRectF &oldGeometry)
491 Q_UNUSED(newGeometry);
492 Q_UNUSED(oldGeometry);
494 updateSizeProperties();
497qreal QQuickRectangularShadowPrivate::getPadding()
const
499 return qreal(m_blur * 2 + m_spread * 2);
502void QQuickRectangularShadowPrivate::updateColor()
504 currentMaterial()->setProperty(
"color", m_color);
507void QQuickRectangularShadowPrivate::updateShaderSource()
509 Q_Q(QQuickRectangularShadow);
510 if (!q->isComponentComplete())
514 m_defaultMaterial->setVisible(
false);
516 updateSizeProperties();
518 currentMaterial()->setVisible(
true);
521void QQuickRectangularShadowPrivate::updateSizeProperties()
523 Q_Q(QQuickRectangularShadow);
524 auto *material = currentMaterial();
526 const qreal padding = getPadding();
527 const qreal clampedRad = clampedRadius();
528 const qreal effectWidth = q->width() + padding;
529 const qreal effectHeight = q->height() + padding;
531 const qreal effectX = (q->width() - effectWidth) * 0.5 + m_offset.x();
532 const qreal effectY = (q->height() - effectHeight) * 0.5 + m_offset.y();
533 material->setX(effectX);
534 material->setY(effectY);
535 material->setWidth(effectWidth);
536 material->setHeight(effectHeight);
538 const qreal aa = q->antialiasing() ? 1.0 : 0.0;
539 material->setProperty(
"iResolution", QVector3D(effectWidth, effectHeight, 1.0));
543 const qreal blurReduction = m_blur * 1.8 + aa;
544 QPointF rectSize = QPointF((effectWidth * 0.5 - blurReduction),
545 (effectHeight * 0.5 - blurReduction));
546 material->setProperty(
"rectSize", rectSize);
547 material->setProperty(
"radius", clampedRad);
550 const qreal shaderBlur = m_blur * 2.1 + aa;
551 material->setProperty(
"blur", shaderBlur);
554void QQuickRectangularShadowPrivate::updateCached()
556 QQuickItemPrivate *effectPrivate = QQuickItemPrivate::get(currentMaterial());
557 effectPrivate->layer()->setEnabled(m_cached);
560qreal QQuickRectangularShadowPrivate::clampedRadius()
const
562 Q_Q(
const QQuickRectangularShadow);
563 qreal maxRadius = qMin(q->width(), q->height()) * 0.5;
564 maxRadius += m_spread * 2;
565 qreal spreadRadius = m_radius + m_spread;
566 if (m_radius < m_spread && !qFuzzyIsNull(m_spread)) {
571 qreal r = (m_radius / m_spread) - 1;
572 spreadRadius = m_radius + m_spread * (1 + r * r * r);
575 const qreal blurReduce = m_blur * 0.75;
576 maxRadius -= blurReduce;
577 const qreal limitedRadius = qMax(0.0, spreadRadius - blurReduce);
578 return qMin(limitedRadius, maxRadius);
581QQuickItem *QQuickRectangularShadowPrivate::currentMaterial()
const
586 return m_defaultMaterial;