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
142
143
144
145
146
147
148
149
152
153
154
155
156
157
158
159
161QQuickRectangularShadow::QQuickRectangularShadow(QQuickItem *parent)
162 : QQuickItem(*
new QQuickRectangularShadowPrivate, parent)
164 setFlag(ItemHasContents);
168
169
170
171
172
173
174
175
176QVector2D QQuickRectangularShadow::offset()
const
178 Q_D(
const QQuickRectangularShadow);
182void QQuickRectangularShadow::setOffset(
const QVector2D &offset)
184 Q_D(QQuickRectangularShadow);
185 if (offset == d->m_offset)
188 d->m_offset = offset;
189 d->updateSizeProperties();
191 Q_EMIT offsetChanged();
195
196
197
198
199
200
201QColor QQuickRectangularShadow::color()
const
203 Q_D(
const QQuickRectangularShadow);
207void QQuickRectangularShadow::setColor(
const QColor &color)
209 Q_D(QQuickRectangularShadow);
210 if (color == d->m_color)
216 Q_EMIT colorChanged();
220
221
222
223
224
225
226
227
228
229
230
231qreal QQuickRectangularShadow::blur()
const
233 Q_D(
const QQuickRectangularShadow);
237void QQuickRectangularShadow::setBlur(qreal blur)
239 Q_D(QQuickRectangularShadow);
240 blur = qMax(qreal(0), blur);
241 if (blur == d->m_blur)
245 d->updateSizeProperties();
247 Q_EMIT blurChanged();
251
252
253
254
255
256
257
258
259
260
261qreal QQuickRectangularShadow::radius()
const
263 Q_D(
const QQuickRectangularShadow);
267void QQuickRectangularShadow::setRadius(qreal radius)
269 Q_D(QQuickRectangularShadow);
270 radius = qMax(qreal(0), radius);
271 if (radius == d->m_radius)
274 d->m_radius = radius;
275 d->maybeSetImplicitAntialiasing();
276 d->updateSizeProperties();
278 Q_EMIT radiusChanged();
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299qreal QQuickRectangularShadow::spread()
const
301 Q_D(
const QQuickRectangularShadow);
305void QQuickRectangularShadow::setSpread(qreal spread)
307 Q_D(QQuickRectangularShadow);
308 if (spread == d->m_spread)
311 d->m_spread = spread;
312 d->updateSizeProperties();
314 Q_EMIT spreadChanged();
318
319
320
321
322
323
324
325
326
327
328
329
330
331bool QQuickRectangularShadow::isCached()
const
333 Q_D(
const QQuickRectangularShadow);
337void QQuickRectangularShadow::setCached(
bool cached)
339 Q_D(QQuickRectangularShadow);
340 if (cached == d->m_cached)
343 d->m_cached = cached;
346 Q_EMIT cachedChanged();
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
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406QQuickItem *QQuickRectangularShadow::material()
const
408 Q_D(
const QQuickRectangularShadow);
409 return d->currentMaterial();
412void QQuickRectangularShadow::setMaterial(QQuickItem *item)
414 Q_D(QQuickRectangularShadow);
415 if (item == d->m_material)
419 item->setParentItem(
this);
423 d->m_material->setVisible(
false);
425 d->m_material = item;
426 d->updateShaderSource();
428 Q_EMIT materialChanged();
432
433
434
435
436
437
438
439
440
441qreal QQuickRectangularShadow::topLeftRadius()
const
443 Q_D(
const QQuickRectangularShadow);
444 if (d->extra.isAllocated() && d->extra->isTopLeftRadiusSet)
445 return d->extra->topLeftRadius;
449void QQuickRectangularShadow::setTopLeftRadius(qreal radius)
451 Q_D(QQuickRectangularShadow);
452 if (d->extra.isAllocated()
453 && d->extra->topLeftRadius == radius
454 && d->extra->isTopLeftRadiusSet) {
458 d->extra.value().topLeftRadius = radius;
459 d->extra.value().isTopLeftRadiusSet =
true;
460 d->maybeSetImplicitAntialiasing();
462 d->updateSizeProperties();
464 emit topLeftRadiusChanged();
467void QQuickRectangularShadow::resetTopLeftRadius()
469 Q_D(QQuickRectangularShadow);
470 if (!d->extra.isAllocated())
472 if (!d->extra->isTopLeftRadiusSet)
475 d->extra->isTopLeftRadiusSet =
false;
476 d->maybeSetImplicitAntialiasing();
478 d->updateSizeProperties();
480 emit topLeftRadiusChanged();
484
485
486
487
488
489
490
491
492
493qreal QQuickRectangularShadow::topRightRadius()
const
495 Q_D(
const QQuickRectangularShadow);
496 if (d->extra.isAllocated() && d->extra->isTopRightRadiusSet)
497 return d->extra->topRightRadius;
501void QQuickRectangularShadow::setTopRightRadius(qreal radius)
503 Q_D(QQuickRectangularShadow);
504 if (d->extra.isAllocated()
505 && d->extra->topRightRadius == radius
506 && d->extra->isTopRightRadiusSet) {
510 d->extra.value().topRightRadius = radius;
511 d->extra.value().isTopRightRadiusSet =
true;
512 d->maybeSetImplicitAntialiasing();
514 d->updateSizeProperties();
516 emit topRightRadiusChanged();
519void QQuickRectangularShadow::resetTopRightRadius()
521 Q_D(QQuickRectangularShadow);
522 if (!d->extra.isAllocated())
524 if (!d->extra.value().isTopRightRadiusSet)
527 d->extra->isTopRightRadiusSet =
false;
528 d->maybeSetImplicitAntialiasing();
530 d->updateSizeProperties();
532 emit topRightRadiusChanged();
536
537
538
539
540
541
542
543
544
545qreal QQuickRectangularShadow::bottomLeftRadius()
const
547 Q_D(
const QQuickRectangularShadow);
548 if (d->extra.isAllocated() && d->extra->isBottomLeftRadiusSet)
549 return d->extra->bottomLeftRadius;
553void QQuickRectangularShadow::setBottomLeftRadius(qreal radius)
555 Q_D(QQuickRectangularShadow);
556 if (d->extra.isAllocated()
557 && d->extra->bottomLeftRadius == radius
558 && d->extra->isBottomLeftRadiusSet) {
562 d->extra.value().bottomLeftRadius = radius;
563 d->extra.value().isBottomLeftRadiusSet =
true;
564 d->maybeSetImplicitAntialiasing();
566 d->updateSizeProperties();
568 emit bottomLeftRadiusChanged();
571void QQuickRectangularShadow::resetBottomLeftRadius()
573 Q_D(QQuickRectangularShadow);
574 if (!d->extra.isAllocated())
576 if (!d->extra.value().isBottomLeftRadiusSet)
579 d->extra->isBottomLeftRadiusSet =
false;
580 d->maybeSetImplicitAntialiasing();
582 d->updateSizeProperties();
584 emit bottomLeftRadiusChanged();
588
589
590
591
592
593
594
595
596
597qreal QQuickRectangularShadow::bottomRightRadius()
const
599 Q_D(
const QQuickRectangularShadow);
600 if (d->extra.isAllocated() && d->extra->isBottomRightRadiusSet)
601 return d->extra->bottomRightRadius;
605void QQuickRectangularShadow::setBottomRightRadius(qreal radius)
607 Q_D(QQuickRectangularShadow);
608 if (d->extra.isAllocated()
609 && d->extra->bottomRightRadius == radius
610 && d->extra->isBottomRightRadiusSet) {
614 d->extra.value().bottomRightRadius = radius;
615 d->extra.value().isBottomRightRadiusSet =
true;
616 d->maybeSetImplicitAntialiasing();
618 d->updateSizeProperties();
620 emit bottomRightRadiusChanged();
623void QQuickRectangularShadow::resetBottomRightRadius()
625 Q_D(QQuickRectangularShadow);
626 if (!d->extra.isAllocated())
628 if (!d->extra.value().isBottomRightRadiusSet)
631 d->extra->isBottomRightRadiusSet =
false;
632 d->maybeSetImplicitAntialiasing();
634 d->updateSizeProperties();
636 emit bottomRightRadiusChanged();
641void QQuickRectangularShadow::componentComplete()
643 Q_D(QQuickRectangularShadow);
644 QQuickItem::componentComplete();
648void QQuickRectangularShadow::geometryChange(
const QRectF &newGeometry,
const QRectF &oldGeometry)
650 Q_D(QQuickRectangularShadow);
651 QQuickItem::geometryChange(newGeometry, oldGeometry);
652 if (width() > 0 && height() > 0)
653 d->handleGeometryChange(newGeometry, oldGeometry);
656void QQuickRectangularShadow::itemChange(ItemChange change,
const ItemChangeData &value)
658 Q_D(QQuickRectangularShadow);
659 d->handleItemChange(change, value);
660 QQuickItem::itemChange(change, value);
665QQuickRectangularShadowPrivate::QQuickRectangularShadowPrivate()
667 Q_Q(QQuickRectangularShadow);
668 m_defaultMaterial =
new QQuickShaderEffect(q);
671 m_defaultMaterial->setProperty(
"iResolution", QVector3D());
672 m_defaultMaterial->setProperty(
"rectSize", QPointF());
673 m_defaultMaterial->setProperty(
"color", QColorConstants::Black);
675 m_defaultMaterial->setProperty(
"radius", 0.0);
676 m_defaultMaterial->setProperty(
"radius4", QVector4D());
677 m_defaultMaterial->setProperty(
"blur", 10.0);
680void QQuickRectangularShadowPrivate::updateDefaultShader()
683 if (useIndividualRadius())
684 fs = QUrl(QStringLiteral(
"qrc:/data/shaders/rectangularshadow4r.frag.qsb"));
686 fs = QUrl(QStringLiteral(
"qrc:/data/shaders/rectangularshadow.frag.qsb"));
687 m_defaultMaterial->setFragmentShader(fs);
690void QQuickRectangularShadowPrivate::initialize()
692 Q_Q(QQuickRectangularShadow);
695 if (!q->isComponentComplete())
699 if (q->width() <= 0 || q->height() <= 0)
702 m_defaultMaterial->setParentItem(q);
703 m_defaultMaterial->setZ(-1);
705 setImplicitAntialiasing(
true);
707 updateDefaultShader();
708 QUrl vs = QUrl(QStringLiteral(
"qrc:/data/shaders/rectangularshadow.vert.qsb"));
709 m_defaultMaterial->setVertexShader(vs);
711 updateShaderSource();
712 m_initialized =
true;
715void QQuickRectangularShadowPrivate::handleItemChange(QQuickItem::ItemChange change,
const QQuickItem::ItemChangeData &value)
718 if (change == QQuickItem::ItemSceneChange)
722void QQuickRectangularShadowPrivate::handleGeometryChange(
const QRectF &newGeometry,
const QRectF &oldGeometry)
724 Q_UNUSED(newGeometry);
725 Q_UNUSED(oldGeometry);
727 updateSizeProperties();
730qreal QQuickRectangularShadowPrivate::getPadding()
const
732 return qreal(m_blur * 2 + m_spread * 2);
735void QQuickRectangularShadowPrivate::updateColor()
737 currentMaterial()->setProperty(
"color", m_color);
740void QQuickRectangularShadowPrivate::updateShaderSource()
742 Q_Q(QQuickRectangularShadow);
743 if (!q->isComponentComplete())
747 m_defaultMaterial->setVisible(
false);
749 updateSizeProperties();
751 currentMaterial()->setVisible(
true);
754void QQuickRectangularShadowPrivate::updateSizeProperties()
756 Q_Q(QQuickRectangularShadow);
759 updateDefaultShader();
761 auto *material = currentMaterial();
763 const qreal padding = getPadding();
764 const qreal effectWidth = q->width() + padding;
765 const qreal effectHeight = q->height() + padding;
767 const qreal effectX = (q->width() - effectWidth) * 0.5 + m_offset.x();
768 const qreal effectY = (q->height() - effectHeight) * 0.5 + m_offset.y();
769 material->setX(effectX);
770 material->setY(effectY);
771 material->setWidth(effectWidth);
772 material->setHeight(effectHeight);
774 const qreal aa = q->antialiasing() ? 1.0 : 0.0;
775 material->setProperty(
"iResolution", QVector3D(effectWidth, effectHeight, 1.0));
779 const qreal blurReduction = m_blur * 1.8 + aa;
780 QPointF rectSize = QPointF((effectWidth * 0.5 - blurReduction),
781 (effectHeight * 0.5 - blurReduction));
782 material->setProperty(
"rectSize", rectSize);
783 if (useIndividualRadius()) {
784 const QVector4D clampedRad4 = clampedRadius4R();
785 material->setProperty(
"radius4", clampedRad4);
786 material->setProperty(
"radius", -1);
788 const qreal clampedRad = clampedRadius(m_radius);
789 material->setProperty(
"radius", clampedRad);
793 const qreal shaderBlur = m_blur * 2.1 + aa;
794 material->setProperty(
"blur", shaderBlur);
797void QQuickRectangularShadowPrivate::updateCached()
799 QQuickItemPrivate *effectPrivate = QQuickItemPrivate::get(currentMaterial());
800 effectPrivate->layer()->setEnabled(m_cached);
803qreal QQuickRectangularShadowPrivate::clampedRadius(qreal radius)
const
805 Q_Q(
const QQuickRectangularShadow);
806 qreal maxRadius = qMin(q->width(), q->height()) * 0.5;
807 maxRadius += m_spread * 2;
808 qreal spreadRadius = radius + m_spread;
809 if (radius < m_spread && !qFuzzyIsNull(m_spread)) {
814 qreal r = (radius / m_spread) - 1;
815 spreadRadius = radius + m_spread * (1 + r * r * r);
818 const qreal blurReduce = m_blur * 0.75;
819 maxRadius -= blurReduce;
820 const qreal limitedRadius = qMax(0.0, spreadRadius - blurReduce);
821 return qMin(limitedRadius, maxRadius);
824QVector4D QQuickRectangularShadowPrivate::clampedRadius4R()
const
826 Q_Q(
const QQuickRectangularShadow);
828 qreal tl = clampedRadius(q->topLeftRadius());
829 qreal tr = clampedRadius(q->topRightRadius());
830 qreal bl = clampedRadius(q->bottomLeftRadius());
831 qreal br = clampedRadius(q->bottomRightRadius());
832 return QVector4D(tl, tr, bl, br);
835QQuickItem *QQuickRectangularShadowPrivate::currentMaterial()
const
840 return m_defaultMaterial;
843void QQuickRectangularShadowPrivate::maybeSetImplicitAntialiasing()
845 bool implicitAA = (m_radius > 0);
846 if (extra.isAllocated() && !implicitAA) {
847 const auto &e = extra.value();
848 implicitAA = (e.isTopLeftRadiusSet && e.topLeftRadius > 0)
849 || (e.isTopRightRadiusSet && e.topRightRadius > 0)
850 || (e.isBottomLeftRadiusSet && e.bottomLeftRadius > 0)
851 || (e.isBottomRightRadiusSet && e.bottomRightRadius > 0);
853 setImplicitAntialiasing(implicitAA);
856bool QQuickRectangularShadowPrivate::useIndividualRadius()
const
858 bool individualRadius =
false;
859 if (extra.isAllocated()) {
860 const auto &e = extra.value();
861 individualRadius = e.isTopLeftRadiusSet
862 || e.isTopRightRadiusSet
863 || e.isBottomLeftRadiusSet
864 || e.isBottomRightRadiusSet;
866 return individualRadius;
Combined button and popup list for selecting options.