source: trunk/src/gui/effects/qgraphicseffect.cpp@ 769

Last change on this file since 769 was 769, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.3 sources from branches/vendor/nokia/qt.

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