Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qgraphicseffect.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5/*!
6 \class QGraphicsEffect
7 \brief The QGraphicsEffect class is the base class for all graphics
8 effects.
9 \since 4.6
10 \ingroup multimedia
11 \ingroup graphicsview-api
12 \inmodule QtWidgets
13
14 Effects alter the appearance of elements by hooking into the rendering
15 pipeline and operating between the source (e.g., a QGraphicsPixmapItem)
16 and the destination device (e.g., QGraphicsView's viewport). Effects can be
17 disabled by calling setEnabled(false). If effects are disabled, the source
18 is rendered directly.
19
20 To add a visual effect to a QGraphicsItem, for example, you can use one of
21 the standard effects, or alternately, create your own effect by creating a
22 subclass of QGraphicsEffect. The effect can then be installed on the item
23 using QGraphicsItem::setGraphicsEffect().
24
25 Qt provides the following standard effects:
26
27 \list
28 \li QGraphicsBlurEffect - blurs the item by a given radius
29 \li QGraphicsDropShadowEffect - renders a dropshadow behind the item
30 \li QGraphicsColorizeEffect - renders the item in shades of any given color
31 \li QGraphicsOpacityEffect - renders the item with an opacity
32 \endlist
33
34 \table
35 \row
36 \li{2,1} \image graphicseffect-plain.png
37 {Image of a fish without any graphical effects}
38 \row
39 \li \image graphicseffect-blur.png
40 {Blur effect on an image of a fish}
41 \li \image graphicseffect-colorize.png
42 {Blue color effect on an image of a fish}
43 \row
44 \li \image graphicseffect-opacity.png
45 {Opacity effect on an image of a fish}
46 \li \image graphicseffect-drop-shadow.png
47 {Drop shadow effect on an image of a fish}
48 \endtable
49
50 \image graphicseffect-widget.png
51 {Opacity drop shadow effects applied on an application}
52
53 For more information on how to use each effect, refer to the specific
54 effect's documentation.
55
56 To create your own custom effect, create a subclass of QGraphicsEffect (or
57 any other existing effects) and reimplement the virtual function draw().
58 This function is called whenever the effect needs to redraw. The draw()
59 function takes the painter with which to draw as an argument. For more
60 information, refer to the documentation for draw(). In the draw() function
61 you can call sourcePixmap() to get a pixmap of the graphics effect source
62 which you can then process.
63
64 If your effect changes, use update() to request for a redraw. If your
65 custom effect changes the bounding rectangle of the source, e.g., a radial
66 glow effect may need to apply an extra margin, you can reimplement the
67 virtual boundingRectFor() function, and call updateBoundingRect()
68 to notify the framework whenever this rectangle changes. The virtual
69 sourceChanged() function is called to notify the effects that
70 the source has changed in some way - e.g., if the source is a
71 QGraphicsRectItem and its rectangle parameters have changed.
72
73 \sa QGraphicsItem::setGraphicsEffect(), QWidget::setGraphicsEffect()
74*/
75
77#include "private/qgraphicsitem_p.h"
78
79#include <QtWidgets/qgraphicsitem.h>
80
81#include <QtGui/qimage.h>
82#include <QtGui/qpainter.h>
83#include <QtGui/qpaintengine.h>
84#include <QtCore/qrect.h>
85#include <QtCore/qdebug.h>
86#include <private/qdrawhelper_p.h>
87
89
90QGraphicsEffectPrivate::~QGraphicsEffectPrivate()
91{
92}
93
94/*!
95 \internal
96 \class QGraphicsEffectSource
97 \brief The QGraphicsEffectSource class represents the source on which a
98 QGraphicsEffect is installed on.
99
100 When a QGraphicsEffect is installed on a QGraphicsItem, for example, this
101 class will act as a wrapper around QGraphicsItem. Then, calling update() is
102 effectively the same as calling QGraphicsItem::update().
103
104 QGraphicsEffectSource also provides a pixmap() function which creates a
105 pixmap with the source painted into it.
106
107 \sa QGraphicsItem::setGraphicsEffect(), QWidget::setGraphicsEffect()
108*/
109
110/*!
111 \internal
112*/
113QGraphicsEffectSource::QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent)
114 : QObject(dd, parent)
115{}
116
117/*!
118 Destroys the effect source.
119*/
120QGraphicsEffectSource::~QGraphicsEffectSource()
121{}
122
123/*!
124 Returns the bounding rectangle of the source mapped to the given \a system.
125
126 \sa draw()
127*/
128QRectF QGraphicsEffectSource::boundingRect(Qt::CoordinateSystem system) const
129{
130 return d_func()->boundingRect(system);
131}
132
133/*!
134 Returns the bounding rectangle of the source mapped to the given \a system.
135
136 Calling this function with Qt::DeviceCoordinates outside of
137 QGraphicsEffect::draw() will give undefined results, as there is no device
138 context available.
139
140 \sa draw()
141*/
142QRectF QGraphicsEffect::sourceBoundingRect(Qt::CoordinateSystem system) const
143{
144 Q_D(const QGraphicsEffect);
145 if (d->source)
146 return d->source->boundingRect(system);
147 return QRectF();
148}
149
150/*!
151 Returns a pointer to the item if this source is a QGraphicsItem; otherwise
152 returns \nullptr.
153
154 \sa widget()
155*/
156const QGraphicsItem *QGraphicsEffectSource::graphicsItem() const
157{
158 return d_func()->graphicsItem();
159}
160
161/*!
162 Returns a pointer to the widget if this source is a QWidget; otherwise
163 returns \nullptr.
164
165 \sa graphicsItem()
166*/
167const QWidget *QGraphicsEffectSource::widget() const
168{
169 return d_func()->widget();
170}
171
172/*!
173 Returns a pointer to the style options (used when drawing the source) if
174 available; otherwise returns \nullptr.
175
176 \sa graphicsItem(), widget()
177*/
178const QStyleOption *QGraphicsEffectSource::styleOption() const
179{
180 return d_func()->styleOption();
181}
182
183/*!
184 Draws the source using the given \a painter.
185
186 This function should only be called from QGraphicsEffect::draw().
187
188 \sa QGraphicsEffect::draw()
189*/
190void QGraphicsEffectSource::draw(QPainter *painter)
191{
192 Q_D(const QGraphicsEffectSource);
193
194 QPixmap pm;
195 if (QPixmapCache::find(d->m_cacheKey, &pm)) {
196 QTransform restoreTransform;
197 if (d->m_cachedSystem == Qt::DeviceCoordinates) {
198 restoreTransform = painter->worldTransform();
199 painter->setWorldTransform(QTransform());
200 }
201
202 painter->drawPixmap(d->m_cachedOffset, pm);
203
204 if (d->m_cachedSystem == Qt::DeviceCoordinates)
205 painter->setWorldTransform(restoreTransform);
206 } else {
207 d_func()->draw(painter);
208 }
209}
210
211/*!
212 Draws the source directly using the given \a painter.
213
214 This function should only be called from QGraphicsEffect::draw().
215
216 For example:
217
218 \snippet code/src_gui_effects_qgraphicseffect.cpp 0
219
220 \sa QGraphicsEffect::draw()
221*/
222void QGraphicsEffect::drawSource(QPainter *painter)
223{
224 Q_D(const QGraphicsEffect);
225 if (d->source)
226 d->source->draw(painter);
227}
228
229/*!
230 Schedules a redraw of the source. Call this function whenever the source
231 needs to be redrawn.
232
233 \sa QGraphicsEffect::updateBoundingRect(), QWidget::update(),
234 QGraphicsItem::update(),
235*/
236void QGraphicsEffectSource::update()
237{
238 d_func()->update();
239}
240
241/*!
242 Returns \c true if the source effectively is a pixmap, e.g., a
243 QGraphicsPixmapItem.
244
245 This function is useful for optimization purposes. For instance, there's no
246 point in drawing the source in device coordinates to avoid pixmap scaling
247 if this function returns \c true - the source pixmap will be scaled anyways.
248*/
249bool QGraphicsEffectSource::isPixmap() const
250{
251 return d_func()->isPixmap();
252}
253
254/*!
255 Returns \c true if the source effectively is a pixmap, e.g., a
256 QGraphicsPixmapItem.
257
258 This function is useful for optimization purposes. For instance, there's no
259 point in drawing the source in device coordinates to avoid pixmap scaling
260 if this function returns \c true - the source pixmap will be scaled anyways.
261*/
262bool QGraphicsEffect::sourceIsPixmap() const
263{
264 return source() ? source()->isPixmap() : false;
265}
266
267/*!
268 Returns a pixmap with the source painted into it.
269
270 The \a system specifies which coordinate system to be used for the source.
271 The optional \a offset parameter returns the offset where the pixmap should
272 be painted at using the current painter.
273
274 The \a mode determines how much of the effect the pixmap will contain.
275 By default, the pixmap will contain the whole effect.
276
277 The returned pixmap is bound to the current painter's device rectangle when
278 \a system is Qt::DeviceCoordinates.
279
280 \sa QGraphicsEffect::draw(), boundingRect()
281*/
282QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offset, QGraphicsEffect::PixmapPadMode mode) const
283{
284 Q_D(const QGraphicsEffectSource);
285
286 // Shortcut, no cache for childless pixmap items...
287 const QGraphicsItem *item = graphicsItem();
288 if (system == Qt::LogicalCoordinates && mode == QGraphicsEffect::NoPad && item && isPixmap()) {
289 const QGraphicsPixmapItem *pixmapItem = static_cast<const QGraphicsPixmapItem *>(item);
290 if (offset)
291 *offset = pixmapItem->offset().toPoint();
292 return pixmapItem->pixmap();
293 }
294
295 if (Q_UNLIKELY(system == Qt::DeviceCoordinates && item &&
296 !static_cast<const QGraphicsItemEffectSourcePrivate *>(d_func())->info)) {
297 qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
298 return QPixmap();
299 }
300
301 QPixmap pm;
302 if (item && d->m_cachedSystem == system && d->m_cachedMode == mode)
303 QPixmapCache::find(d->m_cacheKey, &pm);
304
305 if (pm.isNull()) {
306 pm = d->pixmap(system, &d->m_cachedOffset, mode);
307 d->m_cachedSystem = system;
308 d->m_cachedMode = mode;
309
310 d->invalidateCache();
311 d->m_cacheKey = QPixmapCache::insert(pm);
312 }
313
314 if (offset)
315 *offset = d->m_cachedOffset;
316
317 return pm;
318}
319
320/*!
321 Returns a pixmap with the source painted into it.
322
323 The \a system specifies which coordinate system to be used for the source.
324 The optional \a offset parameter returns the offset where the pixmap should
325 be painted at using the current painter. For control on how the pixmap is
326 padded use the \a mode parameter.
327
328 The returned pixmap is clipped to the current painter's device rectangle when
329 \a system is Qt::DeviceCoordinates.
330
331 Calling this function with Qt::DeviceCoordinates outside of
332 QGraphicsEffect::draw() will give undefined results, as there is no device
333 context available.
334
335 \sa draw(), boundingRect()
336*/
337QPixmap QGraphicsEffect::sourcePixmap(Qt::CoordinateSystem system, QPoint *offset, QGraphicsEffect::PixmapPadMode mode) const
338{
339 Q_D(const QGraphicsEffect);
340 if (d->source)
341 return d->source->pixmap(system, offset, mode);
342 return QPixmap();
343}
344
349
351{
352 m_cachedOffset = offset;
353}
354
355void QGraphicsEffectSourcePrivate::invalidateCache(InvalidateReason reason) const
356{
357 if (m_cachedMode != QGraphicsEffect::PadToEffectiveBoundingRect
358 && (reason == EffectRectChanged
359 || (reason == TransformChanged && m_cachedSystem == Qt::LogicalCoordinates))) {
360 return;
361 }
362
363 QPixmapCache::remove(m_cacheKey);
364}
365
366/*!
367 Constructs a new QGraphicsEffect instance having the
368 specified \a parent.
369*/
370QGraphicsEffect::QGraphicsEffect(QObject *parent)
371 : QObject(*new QGraphicsEffectPrivate, parent)
372{
373}
374
375/*!
376 \internal
377*/
378QGraphicsEffect::QGraphicsEffect(QGraphicsEffectPrivate &dd, QObject *parent)
379 : QObject(dd, parent)
380{
381}
382
383/*!
384 Removes the effect from the source, and destroys the graphics effect.
385*/
386QGraphicsEffect::~QGraphicsEffect()
387{
388 Q_D(QGraphicsEffect);
389 d->setGraphicsEffectSource(nullptr);
390}
391
392/*!
393 Returns the effective bounding rectangle for this effect, i.e., the
394 bounding rectangle of the source in device coordinates, adjusted by
395 any margins applied by the effect itself.
396
397 \sa boundingRectFor(), updateBoundingRect()
398*/
399QRectF QGraphicsEffect::boundingRect() const
400{
401 Q_D(const QGraphicsEffect);
402 if (d->source)
403 return boundingRectFor(d->source->boundingRect());
404 return QRectF();
405}
406
407/*!
408 Returns the effective bounding rectangle for this effect, given the
409 provided \a rect in the device coordinates. When writing
410 you own custom effect, you must call updateBoundingRect() whenever any
411 parameters are changed that may cause this this function to return a
412 different value.
413
414 \sa sourceBoundingRect()
415*/
416QRectF QGraphicsEffect::boundingRectFor(const QRectF &rect) const
417{
418 return rect;
419}
420
421/*!
422 \property QGraphicsEffect::enabled
423 \brief whether the effect is enabled or not.
424
425 If an effect is disabled, the source will be rendered with as normal, with
426 no interference from the effect. If the effect is enabled, the source will
427 be rendered with the effect applied.
428
429 This property is enabled by default.
430
431 Using this property, you can disable certain effects on slow platforms, in
432 order to ensure that the user interface is responsive.
433*/
434bool QGraphicsEffect::isEnabled() const
435{
436 Q_D(const QGraphicsEffect);
437 return d->isEnabled;
438}
439
440void QGraphicsEffect::setEnabled(bool enable)
441{
442 Q_D(QGraphicsEffect);
443 if (d->isEnabled == enable)
444 return;
445
446 d->isEnabled = enable;
447 if (d->source) {
448 d->source->d_func()->effectBoundingRectChanged();
449 d->source->d_func()->invalidateCache();
450 }
451 emit enabledChanged(enable);
452}
453
454/*!
455 \fn void QGraphicsEffect::enabledChanged(bool enabled)
456
457 This signal is emitted whenever the effect is enabled or disabled.
458 The \a enabled parameter holds the effects's new enabled state.
459
460 \sa isEnabled()
461*/
462
463/*!
464 Schedules a redraw of the effect. Call this function whenever the effect
465 needs to be redrawn. This function does not trigger a redraw of the source.
466
467 \sa updateBoundingRect()
468*/
469void QGraphicsEffect::update()
470{
471 Q_D(QGraphicsEffect);
472 if (d->source)
473 d->source->update();
474}
475
476/*!
477 \internal
478
479 Returns a pointer to the source, which provides extra context information
480 that can be useful for the effect.
481
482 \sa draw()
483*/
484QGraphicsEffectSource *QGraphicsEffect::source() const
485{
486 Q_D(const QGraphicsEffect);
487 return d->source;
488}
489
490/*!
491 This function notifies the effect framework when the effect's bounding
492 rectangle has changed. As a custom effect author, you must call this
493 function whenever you change any parameters that will cause the virtual
494 boundingRectFor() function to return a different value.
495
496 This function will call update() if this is necessary.
497
498 \sa boundingRectFor(), boundingRect(), sourceBoundingRect()
499*/
500void QGraphicsEffect::updateBoundingRect()
501{
502 Q_D(QGraphicsEffect);
503 if (d->source) {
504 d->source->d_func()->effectBoundingRectChanged();
505 d->source->d_func()->invalidateCache(QGraphicsEffectSourcePrivate::EffectRectChanged);
506 }
507}
508
509/*!
510 \fn virtual void QGraphicsEffect::draw(QPainter *painter) = 0
511
512 This pure virtual function draws the effect and is called whenever the
513 source needs to be drawn.
514
515 Reimplement this function in a QGraphicsEffect subclass to provide the
516 effect's drawing implementation, using \a painter.
517
518 For example:
519
520 \snippet code/src_gui_effects_qgraphicseffect.cpp 1
521
522 This function should not be called explicitly by the user, since it is
523 meant for reimplementation purposes only.
524*/
525
526/*!
527 \enum QGraphicsEffect::ChangeFlag
528
529 This enum describes what has changed in QGraphicsEffectSource.
530
531 \value SourceAttached The effect is installed on a source.
532 \value SourceDetached The effect is uninstalled on a source.
533 \value SourceBoundingRectChanged The bounding rect of the source has
534 changed.
535 \value SourceInvalidated The visual appearance of the source has changed.
536*/
537
538/*!
539 \enum QGraphicsEffect::PixmapPadMode
540
541 This enum describes how the pixmap returned from sourcePixmap should be
542 padded.
543
544 \value NoPad The pixmap should not receive any additional
545 padding.
546 \value PadToTransparentBorder The pixmap should be padded
547 to ensure it has a completely transparent border.
548 \value PadToEffectiveBoundingRect The pixmap should be padded to
549 match the effective bounding rectangle of the effect.
550*/
551
552/*!
553 This virtual function is called by QGraphicsEffect to notify the effect
554 that the source has changed. If the effect applies any cache, then this
555 cache must be purged in order to reflect the new appearance of the source.
556
557 The \a flags describes what has changed.
558*/
559void QGraphicsEffect::sourceChanged(ChangeFlags flags)
560{
561 Q_UNUSED(flags);
562}
563
564/*!
565 \class QGraphicsColorizeEffect
566 \brief The QGraphicsColorizeEffect class provides a colorize effect.
567 \since 4.6
568 \inmodule QtWidgets
569
570 A colorize effect renders the source with a tint of its color(). The color
571 can be modified using the setColor() function.
572
573 By default, the color is light blue (QColor(0, 0, 192)).
574
575 \image graphicseffect-colorize.png
576 {Blue color effect on an image of a fish}
577
578 \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsOpacityEffect
579*/
580
581/*!
582 Constructs a new QGraphicsColorizeEffect instance.
583 The \a parent parameter is passed to QGraphicsEffect's constructor.
584*/
585QGraphicsColorizeEffect::QGraphicsColorizeEffect(QObject *parent)
586 : QGraphicsEffect(*new QGraphicsColorizeEffectPrivate, parent)
587{
588}
589
590/*!
591 Destroys the effect.
592*/
593QGraphicsColorizeEffect::~QGraphicsColorizeEffect()
594{
595}
596
597/*!
598 \property QGraphicsColorizeEffect::color
599 \brief the color of the effect.
600
601 By default, the color is light blue (QColor(0, 0, 192)).
602*/
603QColor QGraphicsColorizeEffect::color() const
604{
605 Q_D(const QGraphicsColorizeEffect);
606 return d->filter->color();
607}
608
609void QGraphicsColorizeEffect::setColor(const QColor &color)
610{
611 Q_D(QGraphicsColorizeEffect);
612 if (d->filter->color() == color)
613 return;
614
615 d->filter->setColor(color);
616 update();
617 emit colorChanged(color);
618}
619
620/*!
621 \property QGraphicsColorizeEffect::strength
622 \brief the strength of the effect.
623
624 By default, the strength is 1.0.
625 A strength 0.0 equals to no effect, while 1.0 means full colorization.
626*/
627qreal QGraphicsColorizeEffect::strength() const
628{
629 Q_D(const QGraphicsColorizeEffect);
630 return d->filter->strength();
631}
632
633void QGraphicsColorizeEffect::setStrength(qreal strength)
634{
635 Q_D(QGraphicsColorizeEffect);
636 if (qFuzzyCompare(d->filter->strength(), strength))
637 return;
638
639 d->filter->setStrength(strength);
640 d->opaque = !qFuzzyIsNull(strength);
641 update();
642 emit strengthChanged(strength);
643}
644
645/*! \fn void QGraphicsColorizeEffect::strengthChanged(qreal strength)
646 This signal is emitted whenever setStrength() changes the colorize
647 strength property. \a strength contains the new strength value of
648 the colorize effect.
649 */
650
651/*!
652 \fn void QGraphicsColorizeEffect::colorChanged(const QColor &color)
653
654 This signal is emitted whenever the effect's color changes.
655 The \a color parameter holds the effect's new color.
656*/
657
658/*!
659 \reimp
660*/
661void QGraphicsColorizeEffect::draw(QPainter *painter)
662{
663 Q_D(QGraphicsColorizeEffect);
664
665 if (!d->opaque) {
666 drawSource(painter);
667 return;
668 }
669
670 QPoint offset;
671 if (sourceIsPixmap()) {
672 // No point in drawing in device coordinates (pixmap will be scaled anyways).
673 const QPixmap pixmap = sourcePixmap(Qt::LogicalCoordinates, &offset, NoPad);
674 if (!pixmap.isNull())
675 d->filter->draw(painter, offset, pixmap);
676
677 return;
678 }
679
680 // Draw pixmap in deviceCoordinates to avoid pixmap scaling.
681 const QPixmap pixmap = sourcePixmap(Qt::DeviceCoordinates, &offset);
682 if (pixmap.isNull())
683 return;
684
685 QTransform restoreTransform = painter->worldTransform();
686 painter->setWorldTransform(QTransform());
687 d->filter->draw(painter, offset, pixmap);
688 painter->setWorldTransform(restoreTransform);
689}
690
691/*!
692 \class QGraphicsBlurEffect
693 \brief The QGraphicsBlurEffect class provides a blur effect.
694 \since 4.6
695 \inmodule QtWidgets
696
697 A blur effect blurs the source. This effect is useful for reducing details,
698 such as when the source loses focus and you want to draw attention to other
699 elements. The level of detail can be modified using the setBlurRadius()
700 function. Use setBlurHints() to choose the blur hints.
701
702 By default, the blur radius is 5 pixels. The blur radius is specified in
703 device coordinates.
704
705 \image graphicseffect-blur.png
706 {Blur effect on an image of a fish}
707
708 \sa QGraphicsDropShadowEffect, QGraphicsColorizeEffect, QGraphicsOpacityEffect
709*/
710
711/*!
712 \enum QGraphicsBlurEffect::BlurHint
713 \since 4.6
714
715 This enum describes the possible hints that can be used to control how
716 blur effects are applied. The hints might not have an effect in all the
717 paint engines.
718
719 \value PerformanceHint Indicates that rendering performance is the most important factor,
720 at the potential cost of lower quality.
721
722 \value QualityHint Indicates that rendering quality is the most important factor,
723 at the potential cost of lower performance.
724
725 \value AnimationHint Indicates that the blur radius is going to be animated, hinting
726 that the implementation can keep a cache of blurred versions of the source.
727 Do not use this hint if the source is going to be dynamically changing.
728
729 \sa blurHints(), setBlurHints()
730*/
731
732
733/*!
734 Constructs a new QGraphicsBlurEffect instance.
735 The \a parent parameter is passed to QGraphicsEffect's constructor.
736*/
737QGraphicsBlurEffect::QGraphicsBlurEffect(QObject *parent)
738 : QGraphicsEffect(*new QGraphicsBlurEffectPrivate, parent)
739{
740 Q_D(QGraphicsBlurEffect);
741 d->filter->setBlurHints(QGraphicsBlurEffect::PerformanceHint);
742}
743
744/*!
745 Destroys the effect.
746*/
747QGraphicsBlurEffect::~QGraphicsBlurEffect()
748{
749}
750
751/*!
752 \property QGraphicsBlurEffect::blurRadius
753 \brief the blur radius of the effect.
754
755 Using a smaller radius results in a sharper appearance, whereas a bigger
756 radius results in a more blurred appearance.
757
758 By default, the blur radius is 5 pixels.
759
760 The radius is given in device coordinates, meaning it is
761 unaffected by scale.
762*/
763qreal QGraphicsBlurEffect::blurRadius() const
764{
765 Q_D(const QGraphicsBlurEffect);
766 return d->filter->radius();
767}
768
769void QGraphicsBlurEffect::setBlurRadius(qreal radius)
770{
771 Q_D(QGraphicsBlurEffect);
772 if (qFuzzyCompare(d->filter->radius(), radius))
773 return;
774
775 d->filter->setRadius(radius);
776 updateBoundingRect();
777 emit blurRadiusChanged(radius);
778}
779
780/*!
781 \fn void QGraphicsBlurEffect::blurRadiusChanged(qreal radius)
782
783 This signal is emitted whenever the effect's blur radius changes.
784 The \a radius parameter holds the effect's new blur radius.
785*/
786
787/*!
788 \property QGraphicsBlurEffect::blurHints
789 \brief the blur hint of the effect.
790
791 Use the PerformanceHint hint to say that you want a faster blur,
792 the QualityHint hint to say that you prefer a higher quality blur,
793 or the AnimationHint when you want to animate the blur radius.
794
795 By default, the blur hint is PerformanceHint.
796*/
797QGraphicsBlurEffect::BlurHints QGraphicsBlurEffect::blurHints() const
798{
799 Q_D(const QGraphicsBlurEffect);
800 return d->filter->blurHints();
801}
802
803void QGraphicsBlurEffect::setBlurHints(QGraphicsBlurEffect::BlurHints hints)
804{
805 Q_D(QGraphicsBlurEffect);
806 if (d->filter->blurHints() == hints)
807 return;
808
809 d->filter->setBlurHints(hints);
810 emit blurHintsChanged(hints);
811}
812
813/*!
814 \fn void QGraphicsBlurEffect::blurHintsChanged(QGraphicsBlurEffect::BlurHints hints)
815
816 This signal is emitted whenever the effect's blur hints changes.
817 The \a hints parameter holds the effect's new blur hints.
818*/
819
820/*!
821 \reimp
822*/
823QRectF QGraphicsBlurEffect::boundingRectFor(const QRectF &rect) const
824{
825 Q_D(const QGraphicsBlurEffect);
826 return d->filter->boundingRectFor(rect);
827}
828
829/*!
830 \reimp
831*/
832void QGraphicsBlurEffect::draw(QPainter *painter)
833{
834 Q_D(QGraphicsBlurEffect);
835 if (d->filter->radius() < 1) {
836 drawSource(painter);
837 return;
838 }
839
840 PixmapPadMode mode = PadToEffectiveBoundingRect;
841
842 QPoint offset;
843 QPixmap pixmap = sourcePixmap(Qt::LogicalCoordinates, &offset, mode);
844 if (pixmap.isNull())
845 return;
846
847 d->filter->draw(painter, offset, pixmap);
848}
849
850/*!
851 \class QGraphicsDropShadowEffect
852 \brief The QGraphicsDropShadowEffect class provides a drop shadow effect.
853 \since 4.6
854 \inmodule QtWidgets
855
856 A drop shadow effect renders the source with a drop shadow. The color of
857 the drop shadow can be modified using the setColor() function. The drop
858 shadow offset can be modified using the setOffset() function and the blur
859 radius of the drop shadow can be changed with the setBlurRadius()
860 function.
861
862 By default, the drop shadow is a semi-transparent dark gray
863 (QColor(63, 63, 63, 180)) shadow, blurred with a radius of 1 at an offset
864 of 8 pixels towards the lower right. The drop shadow offset is specified
865 in device coordinates.
866
867 \image graphicseffect-drop-shadow.png
868 {Drop shadow effect on an image of a fish}
869
870 \sa QGraphicsBlurEffect, QGraphicsColorizeEffect, QGraphicsOpacityEffect
871*/
872
873/*!
874 Constructs a new QGraphicsDropShadowEffect instance.
875 The \a parent parameter is passed to QGraphicsEffect's constructor.
876*/
877QGraphicsDropShadowEffect::QGraphicsDropShadowEffect(QObject *parent)
878 : QGraphicsEffect(*new QGraphicsDropShadowEffectPrivate, parent)
879{
880}
881
882/*!
883 Destroys the effect.
884*/
885QGraphicsDropShadowEffect::~QGraphicsDropShadowEffect()
886{
887}
888
889/*!
890 \property QGraphicsDropShadowEffect::offset
891 \brief the shadow offset in pixels.
892
893 By default, the offset is 8 pixels towards the lower right.
894
895 The offset is given in device coordinates, which means it is
896 unaffected by scale.
897
898 \sa xOffset(), yOffset(), blurRadius(), color()
899*/
900QPointF QGraphicsDropShadowEffect::offset() const
901{
902 Q_D(const QGraphicsDropShadowEffect);
903 return d->filter->offset();
904}
905
906void QGraphicsDropShadowEffect::setOffset(const QPointF &offset)
907{
908 Q_D(QGraphicsDropShadowEffect);
909 if (d->filter->offset() == offset)
910 return;
911
912 d->filter->setOffset(offset);
913 updateBoundingRect();
914 emit offsetChanged(offset);
915}
916
917/*!
918 \property QGraphicsDropShadowEffect::xOffset
919 \brief the horizontal shadow offset in pixels.
920
921 By default, the horizontal shadow offset is 8 pixels.
922
923
924
925 \sa yOffset(), offset()
926*/
927
928/*!
929 \property QGraphicsDropShadowEffect::yOffset
930 \brief the vertical shadow offset in pixels.
931
932 By default, the vertical shadow offset is 8 pixels.
933
934 \sa xOffset(), offset()
935*/
936
937/*!
938 \fn void QGraphicsDropShadowEffect::offsetChanged(const QPointF &offset)
939
940 This signal is emitted whenever the effect's shadow offset changes.
941 The \a offset parameter holds the effect's new shadow offset.
942*/
943
944/*!
945 \property QGraphicsDropShadowEffect::blurRadius
946 \brief the blur radius in pixels of the drop shadow.
947
948 Using a smaller radius results in a sharper shadow, whereas using a bigger
949 radius results in a more blurred shadow.
950
951 By default, the blur radius is 1 pixel.
952
953 \sa color(), offset()
954*/
955qreal QGraphicsDropShadowEffect::blurRadius() const
956{
957 Q_D(const QGraphicsDropShadowEffect);
958 return d->filter->blurRadius();
959}
960
961void QGraphicsDropShadowEffect::setBlurRadius(qreal blurRadius)
962{
963 Q_D(QGraphicsDropShadowEffect);
964 if (qFuzzyCompare(d->filter->blurRadius(), blurRadius))
965 return;
966
967 d->filter->setBlurRadius(blurRadius);
968 updateBoundingRect();
969 emit blurRadiusChanged(blurRadius);
970}
971
972/*!
973 \fn void QGraphicsDropShadowEffect::blurRadiusChanged(qreal blurRadius)
974
975 This signal is emitted whenever the effect's blur radius changes.
976 The \a blurRadius parameter holds the effect's new blur radius.
977*/
978
979/*!
980 \property QGraphicsDropShadowEffect::color
981 \brief the color of the drop shadow.
982
983 By default, the drop color is a semi-transparent dark gray
984 (QColor(63, 63, 63, 180)).
985
986 \sa offset(), blurRadius()
987*/
988QColor QGraphicsDropShadowEffect::color() const
989{
990 Q_D(const QGraphicsDropShadowEffect);
991 return d->filter->color();
992}
993
994void QGraphicsDropShadowEffect::setColor(const QColor &color)
995{
996 Q_D(QGraphicsDropShadowEffect);
997 if (d->filter->color() == color)
998 return;
999
1000 d->filter->setColor(color);
1001 update();
1002 emit colorChanged(color);
1003}
1004
1005/*!
1006 \fn void QGraphicsDropShadowEffect::colorChanged(const QColor &color)
1007
1008 This signal is emitted whenever the effect's color changes.
1009 The \a color parameter holds the effect's new color.
1010*/
1011
1012/*!
1013 \reimp
1014*/
1015QRectF QGraphicsDropShadowEffect::boundingRectFor(const QRectF &rect) const
1016{
1017 Q_D(const QGraphicsDropShadowEffect);
1018 return d->filter->boundingRectFor(rect);
1019}
1020
1021/*!
1022 \reimp
1023*/
1024void QGraphicsDropShadowEffect::draw(QPainter *painter)
1025{
1026 Q_D(QGraphicsDropShadowEffect);
1027 if (d->filter->blurRadius() <= 0 && d->filter->offset().isNull()) {
1028 drawSource(painter);
1029 return;
1030 }
1031
1032 PixmapPadMode mode = PadToEffectiveBoundingRect;
1033
1034 // Draw pixmap in device coordinates to avoid pixmap scaling.
1035 QPoint offset;
1036 const QPixmap pixmap = sourcePixmap(Qt::DeviceCoordinates, &offset, mode);
1037 if (pixmap.isNull())
1038 return;
1039
1040 QTransform restoreTransform = painter->worldTransform();
1041 painter->setWorldTransform(QTransform());
1042 d->filter->draw(painter, offset, pixmap);
1043 painter->setWorldTransform(restoreTransform);
1044}
1045
1046/*!
1047 \class QGraphicsOpacityEffect
1048 \brief The QGraphicsOpacityEffect class provides an opacity effect.
1049 \since 4.6
1050 \inmodule QtWidgets
1051
1052 An opacity effect renders the source with an opacity. This effect is useful
1053 for making the source semi-transparent, similar to a fade-in/fade-out
1054 sequence. The opacity can be modified using the setOpacity() function.
1055
1056 By default, the opacity is 0.7.
1057
1058 \image graphicseffect-opacity.png
1059 {Opacity effect on an image of a fish}
1060
1061 \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsColorizeEffect
1062*/
1063
1064/*!
1065 Constructs a new QGraphicsOpacityEffect instance.
1066 The \a parent parameter is passed to QGraphicsEffect's constructor.
1067*/
1068QGraphicsOpacityEffect::QGraphicsOpacityEffect(QObject *parent)
1069 : QGraphicsEffect(*new QGraphicsOpacityEffectPrivate, parent)
1070{
1071}
1072
1073/*!
1074 Destroys the effect.
1075*/
1076QGraphicsOpacityEffect::~QGraphicsOpacityEffect()
1077{
1078}
1079
1080/*!
1081 \property QGraphicsOpacityEffect::opacity
1082 \brief the opacity of the effect.
1083
1084 The value should be in the range of 0.0 to 1.0, where 0.0 is
1085 fully transparent and 1.0 is fully opaque.
1086
1087 By default, the opacity is 0.7.
1088
1089 \sa setOpacityMask()
1090*/
1091qreal QGraphicsOpacityEffect::opacity() const
1092{
1093 Q_D(const QGraphicsOpacityEffect);
1094 return d->opacity;
1095}
1096
1097void QGraphicsOpacityEffect::setOpacity(qreal opacity)
1098{
1099 Q_D(QGraphicsOpacityEffect);
1100 opacity = qBound(qreal(0.0), opacity, qreal(1.0));
1101
1102 if (qFuzzyCompare(d->opacity, opacity))
1103 return;
1104
1105 d->opacity = opacity;
1106 if ((d->isFullyTransparent = qFuzzyIsNull(d->opacity)))
1107 d->isFullyOpaque = 0;
1108 else
1109 d->isFullyOpaque = qFuzzyIsNull(d->opacity - 1);
1110 update();
1111 emit opacityChanged(opacity);
1112}
1113
1114/*!
1115 \fn void QGraphicsOpacityEffect::opacityChanged(qreal opacity)
1116
1117 This signal is emitted whenever the effect's opacity changes.
1118 The \a opacity parameter holds the effect's new opacity.
1119*/
1120
1121/*!
1122 \property QGraphicsOpacityEffect::opacityMask
1123 \brief the opacity mask of the effect.
1124
1125 An opacity mask allows you apply opacity to portions of an element.
1126
1127 For example:
1128
1129 \snippet code/src_gui_effects_qgraphicseffect.cpp 2
1130
1131 There is no opacity mask by default.
1132
1133 \sa setOpacity()
1134*/
1135QBrush QGraphicsOpacityEffect::opacityMask() const
1136{
1137 Q_D(const QGraphicsOpacityEffect);
1138 return d->opacityMask;
1139}
1140
1141void QGraphicsOpacityEffect::setOpacityMask(const QBrush &mask)
1142{
1143 Q_D(QGraphicsOpacityEffect);
1144 if (d->opacityMask == mask)
1145 return;
1146
1147 d->opacityMask = mask;
1148 d->hasOpacityMask = (mask.style() != Qt::NoBrush);
1149 update();
1150
1151 emit opacityMaskChanged(mask);
1152}
1153
1154/*!
1155 \fn void QGraphicsOpacityEffect::opacityMaskChanged(const QBrush &mask)
1156
1157 This signal is emitted whenever the effect's opacity mask changes.
1158 The \a mask parameter holds the effect's new opacity mask.
1159*/
1160
1161/*!
1162 \reimp
1163*/
1164void QGraphicsOpacityEffect::draw(QPainter *painter)
1165{
1166 Q_D(QGraphicsOpacityEffect);
1167
1168 // Transparent; nothing to draw.
1169 if (d->isFullyTransparent)
1170 return;
1171
1172 // Opaque; draw directly without going through a pixmap.
1173 if (d->isFullyOpaque && !d->hasOpacityMask) {
1174 drawSource(painter);
1175 return;
1176 }
1177
1178 QPoint offset;
1179 Qt::CoordinateSystem system = sourceIsPixmap() ? Qt::LogicalCoordinates : Qt::DeviceCoordinates;
1180 QPixmap pixmap = sourcePixmap(system, &offset, QGraphicsEffect::NoPad);
1181 if (pixmap.isNull())
1182 return;
1183
1184 painter->save();
1185 painter->setOpacity(d->opacity);
1186
1187 if (d->hasOpacityMask) {
1188 QPainter pixmapPainter(&pixmap);
1189 pixmapPainter.setRenderHints(painter->renderHints());
1190 pixmapPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
1191 if (system == Qt::DeviceCoordinates) {
1192 QTransform worldTransform = painter->worldTransform();
1193 worldTransform *= QTransform::fromTranslate(-offset.x(), -offset.y());
1194 pixmapPainter.setWorldTransform(worldTransform);
1195 pixmapPainter.fillRect(sourceBoundingRect(), d->opacityMask);
1196 } else {
1197 pixmapPainter.translate(-offset);
1198 pixmapPainter.fillRect(pixmap.rect(), d->opacityMask);
1199 }
1200 }
1201
1202 if (system == Qt::DeviceCoordinates)
1203 painter->setWorldTransform(QTransform());
1204
1205 painter->drawPixmap(offset, pixmap);
1206 painter->restore();
1207}
1208
1209
1210QT_END_NAMESPACE
1211
1212#include "moc_qgraphicseffect.cpp"
1213#include "moc_qgraphicseffect_p.cpp"
void setCachedOffset(const QPoint &offset)
void invalidateCache(InvalidateReason reason=SourceChanged) const