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
143
144
145
146
147
148
149
150
152QQuickRectangularShadow::QQuickRectangularShadow(QQuickItem *parent)
153 : QQuickItem(*
new QQuickRectangularShadowPrivate, parent)
155 setFlag(ItemHasContents);
159
160
161
162
163
164
165
166
167QVector2D QQuickRectangularShadow::offset()
const
169 Q_D(
const QQuickRectangularShadow);
173void QQuickRectangularShadow::setOffset(
const QVector2D &offset)
175 Q_D(QQuickRectangularShadow);
176 if (offset == d->m_offset)
179 d->m_offset = offset;
180 d->updateSizeProperties();
182 Q_EMIT offsetChanged();
186
187
188
189
190
191
192QColor QQuickRectangularShadow::color()
const
194 Q_D(
const QQuickRectangularShadow);
198void QQuickRectangularShadow::setColor(
const QColor &color)
200 Q_D(QQuickRectangularShadow);
201 if (color == d->m_color)
207 Q_EMIT colorChanged();
211
212
213
214
215
216
217
218
219
220
221
222qreal QQuickRectangularShadow::blur()
const
224 Q_D(
const QQuickRectangularShadow);
228void QQuickRectangularShadow::setBlur(qreal blur)
230 Q_D(QQuickRectangularShadow);
231 blur = qMax(qreal(0), blur);
232 if (blur == d->m_blur)
236 d->updateSizeProperties();
238 Q_EMIT blurChanged();
242
243
244
245
246
247
248
249
250
251
252qreal QQuickRectangularShadow::radius()
const
254 Q_D(
const QQuickRectangularShadow);
258void QQuickRectangularShadow::setRadius(qreal radius)
260 Q_D(QQuickRectangularShadow);
261 radius = qMax(qreal(0), radius);
262 if (radius == d->m_radius)
265 d->m_radius = radius;
266 d->maybeSetImplicitAntialiasing();
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
392
393
394
395
396
397QQuickItem *QQuickRectangularShadow::material()
const
399 Q_D(
const QQuickRectangularShadow);
400 return d->currentMaterial();
403void QQuickRectangularShadow::setMaterial(QQuickItem *item)
405 Q_D(QQuickRectangularShadow);
406 if (item == d->m_material)
410 item->setParentItem(
this);
414 d->m_material->setVisible(
false);
416 d->m_material = item;
417 d->updateShaderSource();
419 Q_EMIT materialChanged();
423
424
425
426
427
428
429
430
431
432qreal QQuickRectangularShadow::topLeftRadius()
const
434 Q_D(
const QQuickRectangularShadow);
435 if (d->extra.isAllocated() && d->extra->isTopLeftRadiusSet)
436 return d->extra->topLeftRadius;
440void QQuickRectangularShadow::setTopLeftRadius(qreal radius)
442 Q_D(QQuickRectangularShadow);
443 if (d->extra.isAllocated()
444 && d->extra->topLeftRadius == radius
445 && d->extra->isTopLeftRadiusSet) {
449 d->extra.value().topLeftRadius = radius;
450 d->extra.value().isTopLeftRadiusSet =
true;
451 d->maybeSetImplicitAntialiasing();
453 d->updateSizeProperties();
455 emit topLeftRadiusChanged();
458void QQuickRectangularShadow::resetTopLeftRadius()
460 Q_D(QQuickRectangularShadow);
461 if (!d->extra.isAllocated())
463 if (!d->extra->isTopLeftRadiusSet)
466 d->extra->isTopLeftRadiusSet =
false;
467 d->maybeSetImplicitAntialiasing();
469 d->updateSizeProperties();
471 emit topLeftRadiusChanged();
475
476
477
478
479
480
481
482
483
484qreal QQuickRectangularShadow::topRightRadius()
const
486 Q_D(
const QQuickRectangularShadow);
487 if (d->extra.isAllocated() && d->extra->isTopRightRadiusSet)
488 return d->extra->topRightRadius;
492void QQuickRectangularShadow::setTopRightRadius(qreal radius)
494 Q_D(QQuickRectangularShadow);
495 if (d->extra.isAllocated()
496 && d->extra->topRightRadius == radius
497 && d->extra->isTopRightRadiusSet) {
501 d->extra.value().topRightRadius = radius;
502 d->extra.value().isTopRightRadiusSet =
true;
503 d->maybeSetImplicitAntialiasing();
505 d->updateSizeProperties();
507 emit topRightRadiusChanged();
510void QQuickRectangularShadow::resetTopRightRadius()
512 Q_D(QQuickRectangularShadow);
513 if (!d->extra.isAllocated())
515 if (!d->extra.value().isTopRightRadiusSet)
518 d->extra->isTopRightRadiusSet =
false;
519 d->maybeSetImplicitAntialiasing();
521 d->updateSizeProperties();
523 emit topRightRadiusChanged();
527
528
529
530
531
532
533
534
535
536qreal QQuickRectangularShadow::bottomLeftRadius()
const
538 Q_D(
const QQuickRectangularShadow);
539 if (d->extra.isAllocated() && d->extra->isBottomLeftRadiusSet)
540 return d->extra->bottomLeftRadius;
544void QQuickRectangularShadow::setBottomLeftRadius(qreal radius)
546 Q_D(QQuickRectangularShadow);
547 if (d->extra.isAllocated()
548 && d->extra->bottomLeftRadius == radius
549 && d->extra->isBottomLeftRadiusSet) {
553 d->extra.value().bottomLeftRadius = radius;
554 d->extra.value().isBottomLeftRadiusSet =
true;
555 d->maybeSetImplicitAntialiasing();
557 d->updateSizeProperties();
559 emit bottomLeftRadiusChanged();
562void QQuickRectangularShadow::resetBottomLeftRadius()
564 Q_D(QQuickRectangularShadow);
565 if (!d->extra.isAllocated())
567 if (!d->extra.value().isBottomLeftRadiusSet)
570 d->extra->isBottomLeftRadiusSet =
false;
571 d->maybeSetImplicitAntialiasing();
573 d->updateSizeProperties();
575 emit bottomLeftRadiusChanged();
579
580
581
582
583
584
585
586
587
588qreal QQuickRectangularShadow::bottomRightRadius()
const
590 Q_D(
const QQuickRectangularShadow);
591 if (d->extra.isAllocated() && d->extra->isBottomRightRadiusSet)
592 return d->extra->bottomRightRadius;
596void QQuickRectangularShadow::setBottomRightRadius(qreal radius)
598 Q_D(QQuickRectangularShadow);
599 if (d->extra.isAllocated()
600 && d->extra->bottomRightRadius == radius
601 && d->extra->isBottomRightRadiusSet) {
605 d->extra.value().bottomRightRadius = radius;
606 d->extra.value().isBottomRightRadiusSet =
true;
607 d->maybeSetImplicitAntialiasing();
609 d->updateSizeProperties();
611 emit bottomRightRadiusChanged();
614void QQuickRectangularShadow::resetBottomRightRadius()
616 Q_D(QQuickRectangularShadow);
617 if (!d->extra.isAllocated())
619 if (!d->extra.value().isBottomRightRadiusSet)
622 d->extra->isBottomRightRadiusSet =
false;
623 d->maybeSetImplicitAntialiasing();
625 d->updateSizeProperties();
627 emit bottomRightRadiusChanged();
632void QQuickRectangularShadow::componentComplete()
634 Q_D(QQuickRectangularShadow);
635 QQuickItem::componentComplete();
639void QQuickRectangularShadow::geometryChange(
const QRectF &newGeometry,
const QRectF &oldGeometry)
641 Q_D(QQuickRectangularShadow);
642 QQuickItem::geometryChange(newGeometry, oldGeometry);
643 if (width() > 0 && height() > 0)
644 d->handleGeometryChange(newGeometry, oldGeometry);
647void QQuickRectangularShadow::itemChange(ItemChange change,
const ItemChangeData &value)
649 Q_D(QQuickRectangularShadow);
650 d->handleItemChange(change, value);
651 QQuickItem::itemChange(change, value);
656QQuickRectangularShadowPrivate::QQuickRectangularShadowPrivate()
658 Q_Q(QQuickRectangularShadow);
659 m_defaultMaterial =
new QQuickShaderEffect(q);
662 m_defaultMaterial->setProperty(
"iResolution", QVector3D());
663 m_defaultMaterial->setProperty(
"rectSize", QPointF());
664 m_defaultMaterial->setProperty(
"color", QColorConstants::Black);
666 m_defaultMaterial->setProperty(
"radius", 0.0);
667 m_defaultMaterial->setProperty(
"radius4", QVector4D());
668 m_defaultMaterial->setProperty(
"blur", 10.0);
671void QQuickRectangularShadowPrivate::updateDefaultShader()
674 if (useIndividualRadius())
675 fs = QUrl(QStringLiteral(
"qrc:/data/shaders/rectangularshadow4r.frag.qsb"));
677 fs = QUrl(QStringLiteral(
"qrc:/data/shaders/rectangularshadow.frag.qsb"));
678 m_defaultMaterial->setFragmentShader(fs);
681void QQuickRectangularShadowPrivate::initialize()
683 Q_Q(QQuickRectangularShadow);
686 if (!q->isComponentComplete())
690 if (q->width() <= 0 || q->height() <= 0)
693 m_defaultMaterial->setParentItem(q);
694 m_defaultMaterial->setZ(-1);
696 setImplicitAntialiasing(
true);
698 updateDefaultShader();
699 QUrl vs = QUrl(QStringLiteral(
"qrc:/data/shaders/rectangularshadow.vert.qsb"));
700 m_defaultMaterial->setVertexShader(vs);
702 updateShaderSource();
703 m_initialized =
true;
706void QQuickRectangularShadowPrivate::handleItemChange(QQuickItem::ItemChange change,
const QQuickItem::ItemChangeData &value)
709 if (change == QQuickItem::ItemSceneChange)
713void QQuickRectangularShadowPrivate::handleGeometryChange(
const QRectF &newGeometry,
const QRectF &oldGeometry)
715 Q_UNUSED(newGeometry);
716 Q_UNUSED(oldGeometry);
718 updateSizeProperties();
721qreal QQuickRectangularShadowPrivate::getPadding()
const
723 return qreal(m_blur * 2 + m_spread * 2);
726void QQuickRectangularShadowPrivate::updateColor()
728 currentMaterial()->setProperty(
"color", m_color);
731void QQuickRectangularShadowPrivate::updateShaderSource()
733 Q_Q(QQuickRectangularShadow);
734 if (!q->isComponentComplete())
738 m_defaultMaterial->setVisible(
false);
740 updateSizeProperties();
742 currentMaterial()->setVisible(
true);
745void QQuickRectangularShadowPrivate::updateSizeProperties()
747 Q_Q(QQuickRectangularShadow);
750 updateDefaultShader();
752 auto *material = currentMaterial();
754 const qreal padding = getPadding();
755 const qreal effectWidth = q->width() + padding;
756 const qreal effectHeight = q->height() + padding;
758 const qreal effectX = (q->width() - effectWidth) * 0.5 + m_offset.x();
759 const qreal effectY = (q->height() - effectHeight) * 0.5 + m_offset.y();
760 material->setX(effectX);
761 material->setY(effectY);
762 material->setWidth(effectWidth);
763 material->setHeight(effectHeight);
765 const qreal aa = q->antialiasing() ? 1.0 : 0.0;
766 material->setProperty(
"iResolution", QVector3D(effectWidth, effectHeight, 1.0));
770 const qreal blurReduction = m_blur * 1.8 + aa;
771 QPointF rectSize = QPointF((effectWidth * 0.5 - blurReduction),
772 (effectHeight * 0.5 - blurReduction));
773 material->setProperty(
"rectSize", rectSize);
774 if (useIndividualRadius()) {
775 const QVector4D clampedRad4 = clampedRadius4R();
776 material->setProperty(
"radius4", clampedRad4);
777 material->setProperty(
"radius", -1);
779 const qreal clampedRad = clampedRadius(m_radius);
780 material->setProperty(
"radius", clampedRad);
784 const qreal shaderBlur = m_blur * 2.1 + aa;
785 material->setProperty(
"blur", shaderBlur);
788void QQuickRectangularShadowPrivate::updateCached()
790 QQuickItemPrivate *effectPrivate = QQuickItemPrivate::get(currentMaterial());
791 effectPrivate->layer()->setEnabled(m_cached);
794qreal QQuickRectangularShadowPrivate::clampedRadius(qreal radius)
const
796 Q_Q(
const QQuickRectangularShadow);
797 qreal maxRadius = qMin(q->width(), q->height()) * 0.5;
798 maxRadius += m_spread * 2;
799 qreal spreadRadius = radius + m_spread;
800 if (radius < m_spread && !qFuzzyIsNull(m_spread)) {
805 qreal r = (radius / m_spread) - 1;
806 spreadRadius = radius + m_spread * (1 + r * r * r);
809 const qreal blurReduce = m_blur * 0.75;
810 maxRadius -= blurReduce;
811 const qreal limitedRadius = qMax(0.0, spreadRadius - blurReduce);
812 return qMin(limitedRadius, maxRadius);
815QVector4D QQuickRectangularShadowPrivate::clampedRadius4R()
const
817 Q_Q(
const QQuickRectangularShadow);
819 qreal tl = clampedRadius(q->topLeftRadius());
820 qreal tr = clampedRadius(q->topRightRadius());
821 qreal bl = clampedRadius(q->bottomLeftRadius());
822 qreal br = clampedRadius(q->bottomRightRadius());
823 return QVector4D(tl, tr, bl, br);
826QQuickItem *QQuickRectangularShadowPrivate::currentMaterial()
const
831 return m_defaultMaterial;
834void QQuickRectangularShadowPrivate::maybeSetImplicitAntialiasing()
836 bool implicitAA = (m_radius > 0);
837 if (extra.isAllocated() && !implicitAA) {
838 const auto &e = extra.value();
839 implicitAA = (e.isTopLeftRadiusSet && e.topLeftRadius > 0)
840 || (e.isTopRightRadiusSet && e.topRightRadius > 0)
841 || (e.isBottomLeftRadiusSet && e.bottomLeftRadius > 0)
842 || (e.isBottomRightRadiusSet && e.bottomRightRadius > 0);
844 setImplicitAntialiasing(implicitAA);
847bool QQuickRectangularShadowPrivate::useIndividualRadius()
const
849 bool individualRadius =
false;
850 if (extra.isAllocated()) {
851 const auto &e = extra.value();
852 individualRadius = e.isTopLeftRadiusSet
853 || e.isTopRightRadiusSet
854 || e.isBottomLeftRadiusSet
855 || e.isBottomRightRadiusSet;
857 return individualRadius;
Combined button and popup list for selecting options.