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

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

trunk: Merged in qt 4.6.2 sources.

  • Property svn:eol-style set to native
File size: 34.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
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 [email protected].
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
387 && m_cachedSystem == Qt::LogicalCoordinates))
388 return;
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 d->filter->draw(painter, offset, pixmap);
703 return;
704 }
705
706 // Draw pixmap in deviceCoordinates to avoid pixmap scaling.
707 const QPixmap pixmap = sourcePixmap(Qt::DeviceCoordinates, &offset);
708 QTransform restoreTransform = painter->worldTransform();
709 painter->setWorldTransform(QTransform());
710 d->filter->draw(painter, offset, pixmap);
711 painter->setWorldTransform(restoreTransform);
712}
713
714/*!
715 \class QGraphicsBlurEffect
716 \brief The QGraphicsBlurEffect class provides a blur effect.
717 \since 4.6
718
719 A blur effect blurs the source. This effect is useful for reducing details,
720 such as when the source loses focus and you want to draw attention to other
721 elements. The level of detail can be modified using the setBlurRadius()
722 function. Use setBlurHints() to choose the blur hints.
723
724 By default, the blur radius is 5 pixels.
725
726 \img graphicseffect-blur.png
727
728 \sa QGraphicsDropShadowEffect, QGraphicsColorizeEffect, QGraphicsOpacityEffect
729*/
730
731/*!
732 \enum QGraphicsBlurEffect::BlurHint
733 \since 4.6
734
735 This enum describes the possible hints that can be used to control how
736 blur effects are applied. The hints might not have an effect in all the
737 paint engines.
738
739 \value PerformanceHint Indicates that rendering performance is the most important factor,
740 at the potential cost of lower quality.
741
742 \value QualityHint Indicates that rendering quality is the most important factor,
743 at the potential cost of lower performance.
744
745 \value AnimationHint Indicates that the blur radius is going to be animated, hinting
746 that the implementation can keep a cache of blurred verisons of the source.
747 Do not use this hint if the source is going to be dynamically changing.
748
749 \sa blurHints(), setBlurHints()
750*/
751
752
753/*!
754 Constructs a new QGraphicsBlurEffect instance.
755 The \a parent parameter is passed to QGraphicsEffect's constructor.
756*/
757QGraphicsBlurEffect::QGraphicsBlurEffect(QObject *parent)
758 : QGraphicsEffect(*new QGraphicsBlurEffectPrivate, parent)
759{
760 Q_D(QGraphicsBlurEffect);
761 d->filter->setBlurHints(QGraphicsBlurEffect::PerformanceHint);
762}
763
764/*!
765 Destroys the effect.
766*/
767QGraphicsBlurEffect::~QGraphicsBlurEffect()
768{
769}
770
771/*!
772 \property QGraphicsBlurEffect::blurRadius
773 \brief the blur radius of the effect.
774
775 Using a smaller radius results in a sharper appearance, whereas a bigger
776 radius results in a more blurred appearance.
777
778 By default, the blur radius is 5 pixels.
779*/
780qreal QGraphicsBlurEffect::blurRadius() const
781{
782 Q_D(const QGraphicsBlurEffect);
783 return d->filter->radius();
784}
785
786void QGraphicsBlurEffect::setBlurRadius(qreal radius)
787{
788 Q_D(QGraphicsBlurEffect);
789 if (qFuzzyCompare(d->filter->radius(), radius))
790 return;
791
792 d->filter->setRadius(radius);
793 updateBoundingRect();
794 emit blurRadiusChanged(radius);
795}
796
797/*!
798 \fn void QGraphicsBlurEffect::blurRadiusChanged(qreal radius)
799
800 This signal is emitted whenever the effect's blur radius changes.
801 The \a radius parameter holds the effect's new blur radius.
802*/
803
804/*!
805 \property QGraphicsBlurEffect::blurHints
806 \brief the blur hint of the effect.
807
808 Use the PerformanceHint hint to say that you want a faster blur,
809 the QualityHint hint to say that you prefer a higher quality blur,
810 or the AnimationHint when you want to animate the blur radius.
811
812 By default, the blur hint is PerformanceHint.
813*/
814QGraphicsBlurEffect::BlurHints QGraphicsBlurEffect::blurHints() const
815{
816 Q_D(const QGraphicsBlurEffect);
817 return d->filter->blurHints();
818}
819
820void QGraphicsBlurEffect::setBlurHints(QGraphicsBlurEffect::BlurHints hints)
821{
822 Q_D(QGraphicsBlurEffect);
823 if (d->filter->blurHints() == hints)
824 return;
825
826 d->filter->setBlurHints(hints);
827 emit blurHintsChanged(hints);
828}
829
830/*!
831 \fn void QGraphicsBlurEffect::blurHintsChanged(QGraphicsBlurEffect::BlurHints hints)
832
833 This signal is emitted whenever the effect's blur hints changes.
834 The \a hints parameter holds the effect's new blur hints.
835*/
836
837/*!
838 \reimp
839*/
840QRectF QGraphicsBlurEffect::boundingRectFor(const QRectF &rect) const
841{
842 Q_D(const QGraphicsBlurEffect);
843 return d->filter->boundingRectFor(rect);
844}
845
846/*!
847 \reimp
848*/
849void QGraphicsBlurEffect::draw(QPainter *painter)
850{
851 Q_D(QGraphicsBlurEffect);
852 if (d->filter->radius() < 1) {
853 drawSource(painter);
854 return;
855 }
856
857 PixmapPadMode mode = PadToEffectiveBoundingRect;
858 if (painter->paintEngine()->type() == QPaintEngine::OpenGL2)
859 mode = NoPad;
860
861 // Draw pixmap in device coordinates to avoid pixmap scaling.
862 QPoint offset;
863 QPixmap pixmap = sourcePixmap(Qt::LogicalCoordinates, &offset, mode);
864 d->filter->draw(painter, offset, pixmap);
865}
866
867/*!
868 \class QGraphicsDropShadowEffect
869 \brief The QGraphicsDropShadowEffect class provides a drop shadow effect.
870 \since 4.6
871
872 A drop shadow effect renders the source with a drop shadow. The color of
873 the drop shadow can be modified using the setColor() function. The drop
874 shadow offset can be modified using the setOffset() function and the blur
875 radius of the drop shadow can be changed with the setBlurRadius()
876 function.
877
878 By default, the drop shadow is a semi-transparent dark gray
879 (QColor(63, 63, 63, 180)) shadow, blurred with a radius of 1 at an offset
880 of 8 pixels towards the lower right.
881
882 \img graphicseffect-drop-shadow.png
883
884 \sa QGraphicsBlurEffect, QGraphicsColorizeEffect, QGraphicsOpacityEffect
885*/
886
887/*!
888 Constructs a new QGraphicsDropShadowEffect instance.
889 The \a parent parameter is passed to QGraphicsEffect's constructor.
890*/
891QGraphicsDropShadowEffect::QGraphicsDropShadowEffect(QObject *parent)
892 : QGraphicsEffect(*new QGraphicsDropShadowEffectPrivate, parent)
893{
894}
895
896/*!
897 Destroys the effect.
898*/
899QGraphicsDropShadowEffect::~QGraphicsDropShadowEffect()
900{
901}
902
903/*!
904 \property QGraphicsDropShadowEffect::offset
905 \brief the shadow offset in pixels.
906
907 By default, the offset is 8 pixels towards the lower right.
908
909 \sa xOffset(), yOffset(), blurRadius(), color()
910*/
911QPointF QGraphicsDropShadowEffect::offset() const
912{
913 Q_D(const QGraphicsDropShadowEffect);
914 return d->filter->offset();
915}
916
917void QGraphicsDropShadowEffect::setOffset(const QPointF &offset)
918{
919 Q_D(QGraphicsDropShadowEffect);
920 if (d->filter->offset() == offset)
921 return;
922
923 d->filter->setOffset(offset);
924 updateBoundingRect();
925 emit offsetChanged(offset);
926}
927
928/*!
929 \property QGraphicsDropShadowEffect::xOffset
930 \brief the horizontal shadow offset in pixels.
931
932 By default, the horizontal shadow offset is 8 pixels.
933
934
935
936 \sa yOffset(), offset()
937*/
938
939/*!
940 \property QGraphicsDropShadowEffect::yOffset
941 \brief the vertical shadow offset in pixels.
942
943 By default, the vertical shadow offset is 8 pixels.
944
945 \sa xOffset(), offset()
946*/
947
948/*!
949 \fn void QGraphicsDropShadowEffect::offsetChanged(const QPointF &offset)
950
951 This signal is emitted whenever the effect's shadow offset changes.
952 The \a offset parameter holds the effect's new shadow offset.
953*/
954
955/*!
956 \property QGraphicsDropShadowEffect::blurRadius
957 \brief the blur radius in pixels of the drop shadow.
958
959 Using a smaller radius results in a sharper shadow, whereas using a bigger
960 radius results in a more blurred shadow.
961
962 By default, the blur radius is 1 pixel.
963
964 \sa color(), offset().
965*/
966qreal QGraphicsDropShadowEffect::blurRadius() const
967{
968 Q_D(const QGraphicsDropShadowEffect);
969 return d->filter->blurRadius();
970}
971
972void QGraphicsDropShadowEffect::setBlurRadius(qreal blurRadius)
973{
974 Q_D(QGraphicsDropShadowEffect);
975 if (qFuzzyCompare(d->filter->blurRadius(), blurRadius))
976 return;
977
978 d->filter->setBlurRadius(blurRadius);
979 updateBoundingRect();
980 emit blurRadiusChanged(blurRadius);
981}
982
983/*!
984 \fn void QGraphicsDropShadowEffect::blurRadiusChanged(qreal blurRadius)
985
986 This signal is emitted whenever the effect's blur radius changes.
987 The \a blurRadius parameter holds the effect's new blur radius.
988*/
989
990/*!
991 \property QGraphicsDropShadowEffect::color
992 \brief the color of the drop shadow.
993
994 By default, the drop color is a semi-transparent dark gray
995 (QColor(63, 63, 63, 180)).
996
997 \sa offset(), blurRadius()
998*/
999QColor QGraphicsDropShadowEffect::color() const
1000{
1001 Q_D(const QGraphicsDropShadowEffect);
1002 return d->filter->color();
1003}
1004
1005void QGraphicsDropShadowEffect::setColor(const QColor &color)
1006{
1007 Q_D(QGraphicsDropShadowEffect);
1008 if (d->filter->color() == color)
1009 return;
1010
1011 d->filter->setColor(color);
1012 update();
1013 emit colorChanged(color);
1014}
1015
1016/*!
1017 \fn void QGraphicsDropShadowEffect::colorChanged(const QColor &color)
1018
1019 This signal is emitted whenever the effect's color changes.
1020 The \a color parameter holds the effect's new color.
1021*/
1022
1023/*!
1024 \reimp
1025*/
1026QRectF QGraphicsDropShadowEffect::boundingRectFor(const QRectF &rect) const
1027{
1028 Q_D(const QGraphicsDropShadowEffect);
1029 return d->filter->boundingRectFor(rect);
1030}
1031
1032/*!
1033 \reimp
1034*/
1035void QGraphicsDropShadowEffect::draw(QPainter *painter)
1036{
1037 Q_D(QGraphicsDropShadowEffect);
1038 if (d->filter->blurRadius() <= 0 && d->filter->offset().isNull()) {
1039 drawSource(painter);
1040 return;
1041 }
1042
1043 PixmapPadMode mode = PadToEffectiveBoundingRect;
1044 if (painter->paintEngine()->type() == QPaintEngine::OpenGL2)
1045 mode = NoPad;
1046
1047 // Draw pixmap in device coordinates to avoid pixmap scaling.
1048 QPoint offset;
1049 const QPixmap pixmap = sourcePixmap(Qt::DeviceCoordinates, &offset, mode);
1050 QTransform restoreTransform = painter->worldTransform();
1051 painter->setWorldTransform(QTransform());
1052 d->filter->draw(painter, offset, pixmap);
1053 painter->setWorldTransform(restoreTransform);
1054}
1055
1056/*!
1057 \class QGraphicsOpacityEffect
1058 \brief The QGraphicsOpacityEffect class provides an opacity effect.
1059 \since 4.6
1060
1061 An opacity effect renders the source with an opacity. This effect is useful
1062 for making the source semi-transparent, similar to a fade-in/fade-out
1063 sequence. The opacity can be modified using the setOpacity() function.
1064
1065 By default, the opacity is 0.7.
1066
1067 \img graphicseffect-opacity.png
1068
1069 \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsColorizeEffect
1070*/
1071
1072/*!
1073 Constructs a new QGraphicsOpacityEffect instance.
1074 The \a parent parameter is passed to QGraphicsEffect's constructor.
1075*/
1076QGraphicsOpacityEffect::QGraphicsOpacityEffect(QObject *parent)
1077 : QGraphicsEffect(*new QGraphicsOpacityEffectPrivate, parent)
1078{
1079}
1080
1081/*!
1082 Destroys the effect.
1083*/
1084QGraphicsOpacityEffect::~QGraphicsOpacityEffect()
1085{
1086}
1087
1088/*!
1089 \property QGraphicsOpacityEffect::opacity
1090 \brief the opacity of the effect.
1091
1092 The value should be in the range of 0.0 to 1.0, where 0.0 is
1093 fully transparent and 1.0 is fully opaque.
1094
1095 By default, the opacity is 0.7.
1096
1097 \sa setOpacityMask()
1098*/
1099qreal QGraphicsOpacityEffect::opacity() const
1100{
1101 Q_D(const QGraphicsOpacityEffect);
1102 return d->opacity;
1103}
1104
1105void QGraphicsOpacityEffect::setOpacity(qreal opacity)
1106{
1107 Q_D(QGraphicsOpacityEffect);
1108 opacity = qBound(qreal(0.0), opacity, qreal(1.0));
1109
1110 if (qFuzzyCompare(d->opacity, opacity))
1111 return;
1112
1113 d->opacity = opacity;
1114 if ((d->isFullyTransparent = qFuzzyIsNull(d->opacity)))
1115 d->isFullyOpaque = 0;
1116 else
1117 d->isFullyOpaque = qFuzzyIsNull(d->opacity - 1);
1118 update();
1119 emit opacityChanged(opacity);
1120}
1121
1122/*!
1123 \fn void QGraphicsOpacityEffect::opacityChanged(qreal opacity)
1124
1125 This signal is emitted whenever the effect's opacity changes.
1126 The \a opacity parameter holds the effect's new opacity.
1127*/
1128
1129/*!
1130 \property QGraphicsOpacityEffect::opacityMask
1131 \brief the opacity mask of the effect.
1132
1133 An opacity mask allows you apply opacity to portions of an element.
1134
1135 For example:
1136
1137 \snippet doc/src/snippets/code/src_gui_effects_qgraphicseffect.cpp 2
1138
1139 There is no opacity mask by default.
1140
1141 \sa setOpacity()
1142*/
1143QBrush QGraphicsOpacityEffect::opacityMask() const
1144{
1145 Q_D(const QGraphicsOpacityEffect);
1146 return d->opacityMask;
1147}
1148
1149void QGraphicsOpacityEffect::setOpacityMask(const QBrush &mask)
1150{
1151 Q_D(QGraphicsOpacityEffect);
1152 if (d->opacityMask == mask)
1153 return;
1154
1155 d->opacityMask = mask;
1156 d->hasOpacityMask = (mask.style() != Qt::NoBrush);
1157 update();
1158
1159 emit opacityMaskChanged(mask);
1160}
1161
1162/*!
1163 \fn void QGraphicsOpacityEffect::opacityMaskChanged(const QBrush &mask)
1164
1165 This signal is emitted whenever the effect's opacity mask changes.
1166 The \a mask parameter holds the effect's new opacity mask.
1167*/
1168
1169/*!
1170 \reimp
1171*/
1172void QGraphicsOpacityEffect::draw(QPainter *painter)
1173{
1174 Q_D(QGraphicsOpacityEffect);
1175
1176 // Transparent; nothing to draw.
1177 if (d->isFullyTransparent)
1178 return;
1179
1180 // Opaque; draw directly without going through a pixmap.
1181 if (d->isFullyOpaque && !d->hasOpacityMask) {
1182 drawSource(painter);
1183 return;
1184 }
1185
1186 QPoint offset;
1187 Qt::CoordinateSystem system = sourceIsPixmap() ? Qt::LogicalCoordinates : Qt::DeviceCoordinates;
1188 QPixmap pixmap = sourcePixmap(system, &offset, QGraphicsEffect::NoPad);
1189 if (pixmap.isNull())
1190 return;
1191
1192 painter->save();
1193 painter->setOpacity(d->opacity);
1194
1195 if (d->hasOpacityMask) {
1196 QPainter pixmapPainter(&pixmap);
1197 pixmapPainter.setRenderHints(painter->renderHints());
1198 pixmapPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
1199 if (system == Qt::DeviceCoordinates) {
1200 QTransform worldTransform = painter->worldTransform();
1201 worldTransform *= QTransform::fromTranslate(-offset.x(), -offset.y());
1202 pixmapPainter.setWorldTransform(worldTransform);
1203 pixmapPainter.fillRect(sourceBoundingRect(), d->opacityMask);
1204 } else {
1205 pixmapPainter.translate(-offset);
1206 pixmapPainter.fillRect(pixmap.rect(), d->opacityMask);
1207 }
1208 }
1209
1210 if (system == Qt::DeviceCoordinates)
1211 painter->setWorldTransform(QTransform());
1212
1213 painter->drawPixmap(offset, pixmap);
1214 painter->restore();
1215}
1216
1217
1218QT_END_NAMESPACE
1219
1220#endif //QT_NO_GRAPHICSEFFECT
Note: See TracBrowser for help on using the repository browser.