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

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

trunk: Merged in qt 4.6.1 sources.

  • Property svn:eol-style set to native
File size: 34.4 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 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::invalidateCache(InvalidateReason reason) const
378{
379 if (m_cachedMode != QGraphicsEffect::PadToEffectiveBoundingRect
380 && (reason == EffectRectChanged
381 || reason == TransformChanged
382 && m_cachedSystem == Qt::LogicalCoordinates))
383 return;
384
385 QPixmapCache::remove(m_cacheKey);
386}
387
388/*!
389 Constructs a new QGraphicsEffect instance having the
390 specified \a parent.
391*/
392QGraphicsEffect::QGraphicsEffect(QObject *parent)
393 : QObject(*new QGraphicsEffectPrivate, parent)
394{
395}
396
397/*!
398 \internal
399*/
400QGraphicsEffect::QGraphicsEffect(QGraphicsEffectPrivate &dd, QObject *parent)
401 : QObject(dd, parent)
402{
403}
404
405/*!
406 Removes the effect from the source, and destroys the graphics effect.
407*/
408QGraphicsEffect::~QGraphicsEffect()
409{
410 Q_D(QGraphicsEffect);
411 d->setGraphicsEffectSource(0);
412}
413
414/*!
415 Returns the effective bounding rectangle for this effect, i.e., the
416 bounding rectangle of the source in device coordinates, adjusted by
417 any margins applied by the effect itself.
418
419 \sa boundingRectFor(), updateBoundingRect()
420*/
421QRectF QGraphicsEffect::boundingRect() const
422{
423 Q_D(const QGraphicsEffect);
424 if (d->source)
425 return boundingRectFor(d->source->boundingRect());
426 return QRectF();
427}
428
429/*!
430 Returns the effective bounding rectangle for this effect, given the
431 provided \a rect in the device coordinates. When writing
432 you own custom effect, you must call updateBoundingRect() whenever any
433 parameters are changed that may cause this this function to return a
434 different value.
435
436 \sa sourceBoundingRect()
437*/
438QRectF QGraphicsEffect::boundingRectFor(const QRectF &rect) const
439{
440 return rect;
441}
442
443/*!
444 \property QGraphicsEffect::enabled
445 \brief whether the effect is enabled or not.
446
447 If an effect is disabled, the source will be rendered with as normal, with
448 no interference from the effect. If the effect is enabled, the source will
449 be rendered with the effect applied.
450
451 This property is enabled by default.
452
453 Using this property, you can disable certain effects on slow platforms, in
454 order to ensure that the user interface is responsive.
455*/
456bool QGraphicsEffect::isEnabled() const
457{
458 Q_D(const QGraphicsEffect);
459 return d->isEnabled;
460}
461
462void QGraphicsEffect::setEnabled(bool enable)
463{
464 Q_D(QGraphicsEffect);
465 if (d->isEnabled == enable)
466 return;
467
468 d->isEnabled = enable;
469 if (d->source) {
470 d->source->d_func()->effectBoundingRectChanged();
471 d->source->d_func()->invalidateCache();
472 }
473 emit enabledChanged(enable);
474}
475
476/*!
477 \fn void QGraphicsEffect::enabledChanged(bool enabled)
478
479 This signal is emitted whenever the effect is enabled or disabled.
480 The \a enabled parameter holds the effects's new enabled state.
481
482 \sa isEnabled()
483*/
484
485/*!
486 Schedules a redraw of the source. Call this function whenever the source
487 needs to be redrawn.
488
489 This convenience function is equivalent to calling
490 QGraphicsEffectSource::update().
491
492 \sa updateBoundingRect(), QGraphicsEffectSource::update()
493*/
494void QGraphicsEffect::update()
495{
496 Q_D(QGraphicsEffect);
497 if (d->source)
498 d->source->update();
499}
500
501/*!
502 \internal
503
504 Returns a pointer to the source, which provides extra context information
505 that can be useful for the effect.
506
507 \sa draw()
508*/
509QGraphicsEffectSource *QGraphicsEffect::source() const
510{
511 Q_D(const QGraphicsEffect);
512 return d->source;
513}
514
515/*!
516 This function notifies the effect framework when the effect's bounding
517 rectangle has changed. As a custom effect author, you must call this
518 function whenever you change any parameters that will cause the virtual
519 boundingRectFor() function to return a different value.
520
521 This function will call update() if this is necessary.
522
523 \sa boundingRectFor(), boundingRect(), sourceBoundingRect()
524*/
525void QGraphicsEffect::updateBoundingRect()
526{
527 Q_D(QGraphicsEffect);
528 if (d->source) {
529 d->source->d_func()->effectBoundingRectChanged();
530 d->source->d_func()->invalidateCache(QGraphicsEffectSourcePrivate::EffectRectChanged);
531 }
532}
533
534/*!
535 \fn virtual void QGraphicsEffect::draw(QPainter *painter) = 0
536
537 This pure virtual function draws the effect and is called whenever the
538 source needs to be drawn.
539
540 Reimplement this function in a QGraphicsEffect subclass to provide the
541 effect's drawing implementation, using \a painter.
542
543 For example:
544
545 \snippet doc/src/snippets/code/src_gui_effects_qgraphicseffect.cpp 1
546
547 This function should not be called explicitly by the user, since it is
548 meant for reimplementation purposes only.
549*/
550
551/*!
552 \enum QGraphicsEffect::ChangeFlag
553
554 This enum describes what has changed in QGraphicsEffectSource.
555
556 \value SourceAttached The effect is installed on a source.
557 \value SourceDetached The effect is uninstalled on a source.
558 \value SourceBoundingRectChanged The bounding rect of the source has
559 changed.
560 \value SourceInvalidated The visual appearance of the source has changed.
561*/
562
563/*!
564 \enum QGraphicsEffect::PixmapPadMode
565
566 This enum describes how the pixmap returned from sourcePixmap should be
567 padded.
568
569 \value NoPad The pixmap should not receive any additional
570 padding.
571 \value PadToTransparentBorder The pixmap should be padded
572 to ensure it has a completely transparent border.
573 \value PadToEffectiveBoundingRect The pixmap should be padded to
574 match the effective bounding rectangle of the effect.
575*/
576
577/*!
578 This virtual function is called by QGraphicsEffect to notify the effect
579 that the source has changed. If the effect applies any cache, then this
580 cache must be purged in order to reflect the new appearance of the source.
581
582 The \a flags describes what has changed.
583*/
584void QGraphicsEffect::sourceChanged(ChangeFlags flags)
585{
586 Q_UNUSED(flags);
587}
588
589/*!
590 \class QGraphicsColorizeEffect
591 \brief The QGraphicsColorizeEffect class provides a colorize effect.
592 \since 4.6
593
594 A colorize effect renders the source with a tint of its color(). The color
595 can be modified using the setColor() function.
596
597 By default, the color is light blue (QColor(0, 0, 192)).
598
599 \img graphicseffect-colorize.png
600
601 \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsOpacityEffect
602*/
603
604/*!
605 Constructs a new QGraphicsColorizeEffect instance.
606 The \a parent parameter is passed to QGraphicsEffect's constructor.
607*/
608QGraphicsColorizeEffect::QGraphicsColorizeEffect(QObject *parent)
609 : QGraphicsEffect(*new QGraphicsColorizeEffectPrivate, parent)
610{
611}
612
613/*!
614 Destroys the effect.
615*/
616QGraphicsColorizeEffect::~QGraphicsColorizeEffect()
617{
618}
619
620/*!
621 \property QGraphicsColorizeEffect::color
622 \brief the color of the effect.
623
624 By default, the color is light blue (QColor(0, 0, 192)).
625*/
626QColor QGraphicsColorizeEffect::color() const
627{
628 Q_D(const QGraphicsColorizeEffect);
629 return d->filter->color();
630}
631
632void QGraphicsColorizeEffect::setColor(const QColor &color)
633{
634 Q_D(QGraphicsColorizeEffect);
635 if (d->filter->color() == color)
636 return;
637
638 d->filter->setColor(color);
639 update();
640 emit colorChanged(color);
641}
642
643/*!
644 \property QGraphicsColorizeEffect::strength
645 \brief the strength of the effect.
646
647 By default, the strength is 1.0.
648 A strength 0.0 equals to no effect, while 1.0 means full colorization.
649*/
650qreal QGraphicsColorizeEffect::strength() const
651{
652 Q_D(const QGraphicsColorizeEffect);
653 return d->filter->strength();
654}
655
656void QGraphicsColorizeEffect::setStrength(qreal strength)
657{
658 Q_D(QGraphicsColorizeEffect);
659 if (qFuzzyCompare(d->filter->strength(), strength))
660 return;
661
662 d->filter->setStrength(strength);
663 d->opaque = !qFuzzyIsNull(strength);
664 update();
665 emit strengthChanged(strength);
666}
667
668/*! \fn void QGraphicsColorizeEffect::strengthChanged(qreal strength)
669 This signal is emitted whenever setStrength() changes the colorize
670 strength property. \a strength contains the new strength value of
671 the colorize effect.
672 */
673
674/*!
675 \fn void QGraphicsColorizeEffect::colorChanged(const QColor &color)
676
677 This signal is emitted whenever the effect's color changes.
678 The \a color parameter holds the effect's new color.
679*/
680
681/*!
682 \reimp
683*/
684void QGraphicsColorizeEffect::draw(QPainter *painter)
685{
686 Q_D(QGraphicsColorizeEffect);
687
688 if (!d->opaque) {
689 drawSource(painter);
690 return;
691 }
692
693 QPoint offset;
694 if (sourceIsPixmap()) {
695 // No point in drawing in device coordinates (pixmap will be scaled anyways).
696 const QPixmap pixmap = sourcePixmap(Qt::LogicalCoordinates, &offset, NoPad);
697 d->filter->draw(painter, offset, pixmap);
698 return;
699 }
700
701 // Draw pixmap in deviceCoordinates to avoid pixmap scaling.
702 const QPixmap pixmap = sourcePixmap(Qt::DeviceCoordinates, &offset);
703 QTransform restoreTransform = painter->worldTransform();
704 painter->setWorldTransform(QTransform());
705 d->filter->draw(painter, offset, pixmap);
706 painter->setWorldTransform(restoreTransform);
707}
708
709/*!
710 \class QGraphicsBlurEffect
711 \brief The QGraphicsBlurEffect class provides a blur effect.
712 \since 4.6
713
714 A blur effect blurs the source. This effect is useful for reducing details,
715 such as when the source loses focus and you want to draw attention to other
716 elements. The level of detail can be modified using the setBlurRadius()
717 function. Use setBlurHints() to choose the blur hints.
718
719 By default, the blur radius is 5 pixels.
720
721 \img graphicseffect-blur.png
722
723 \sa QGraphicsDropShadowEffect, QGraphicsColorizeEffect, QGraphicsOpacityEffect
724*/
725
726/*!
727 \enum QGraphicsBlurEffect::BlurHint
728 \since 4.6
729
730 This enum describes the possible hints that can be used to control how
731 blur effects are applied. The hints might not have an effect in all the
732 paint engines.
733
734 \value PerformanceHint Indicates that rendering performance is the most important factor,
735 at the potential cost of lower quality.
736
737 \value QualityHint Indicates that rendering quality is the most important factor,
738 at the potential cost of lower performance.
739
740 \value AnimationHint Indicates that the blur radius is going to be animated, hinting
741 that the implementation can keep a cache of blurred verisons of the source.
742 Do not use this hint if the source is going to be dynamically changing.
743
744 \sa blurHints(), setBlurHints()
745*/
746
747
748/*!
749 Constructs a new QGraphicsBlurEffect instance.
750 The \a parent parameter is passed to QGraphicsEffect's constructor.
751*/
752QGraphicsBlurEffect::QGraphicsBlurEffect(QObject *parent)
753 : QGraphicsEffect(*new QGraphicsBlurEffectPrivate, parent)
754{
755 Q_D(QGraphicsBlurEffect);
756 d->filter->setBlurHints(QGraphicsBlurEffect::PerformanceHint);
757}
758
759/*!
760 Destroys the effect.
761*/
762QGraphicsBlurEffect::~QGraphicsBlurEffect()
763{
764}
765
766/*!
767 \property QGraphicsBlurEffect::blurRadius
768 \brief the blur radius of the effect.
769
770 Using a smaller radius results in a sharper appearance, whereas a bigger
771 radius results in a more blurred appearance.
772
773 By default, the blur radius is 5 pixels.
774*/
775qreal QGraphicsBlurEffect::blurRadius() const
776{
777 Q_D(const QGraphicsBlurEffect);
778 return d->filter->radius();
779}
780
781void QGraphicsBlurEffect::setBlurRadius(qreal radius)
782{
783 Q_D(QGraphicsBlurEffect);
784 if (qFuzzyCompare(d->filter->radius(), radius))
785 return;
786
787 d->filter->setRadius(radius);
788 updateBoundingRect();
789 emit blurRadiusChanged(radius);
790}
791
792/*!
793 \fn void QGraphicsBlurEffect::blurRadiusChanged(qreal radius)
794
795 This signal is emitted whenever the effect's blur radius changes.
796 The \a radius parameter holds the effect's new blur radius.
797*/
798
799/*!
800 \property QGraphicsBlurEffect::blurHints
801 \brief the blur hint of the effect.
802
803 Use the PerformanceHint hint to say that you want a faster blur,
804 the QualityHint hint to say that you prefer a higher quality blur,
805 or the AnimationHint when you want to animate the blur radius.
806
807 By default, the blur hint is PerformanceHint.
808*/
809QGraphicsBlurEffect::BlurHints QGraphicsBlurEffect::blurHints() const
810{
811 Q_D(const QGraphicsBlurEffect);
812 return d->filter->blurHints();
813}
814
815void QGraphicsBlurEffect::setBlurHints(QGraphicsBlurEffect::BlurHints hints)
816{
817 Q_D(QGraphicsBlurEffect);
818 if (d->filter->blurHints() == hints)
819 return;
820
821 d->filter->setBlurHints(hints);
822 emit blurHintsChanged(hints);
823}
824
825/*!
826 \fn void QGraphicsBlurEffect::blurHintsChanged(QGraphicsBlurEffect::BlurHints hints)
827
828 This signal is emitted whenever the effect's blur hints changes.
829 The \a hints parameter holds the effect's new blur hints.
830*/
831
832/*!
833 \reimp
834*/
835QRectF QGraphicsBlurEffect::boundingRectFor(const QRectF &rect) const
836{
837 Q_D(const QGraphicsBlurEffect);
838 return d->filter->boundingRectFor(rect);
839}
840
841/*!
842 \reimp
843*/
844void QGraphicsBlurEffect::draw(QPainter *painter)
845{
846 Q_D(QGraphicsBlurEffect);
847 if (d->filter->radius() < 1) {
848 drawSource(painter);
849 return;
850 }
851
852 PixmapPadMode mode = PadToEffectiveBoundingRect;
853 if (painter->paintEngine()->type() == QPaintEngine::OpenGL2)
854 mode = NoPad;
855
856 // Draw pixmap in device coordinates to avoid pixmap scaling.
857 QPoint offset;
858 QPixmap pixmap = sourcePixmap(Qt::LogicalCoordinates, &offset, mode);
859 d->filter->draw(painter, offset, pixmap);
860}
861
862/*!
863 \class QGraphicsDropShadowEffect
864 \brief The QGraphicsDropShadowEffect class provides a drop shadow effect.
865 \since 4.6
866
867 A drop shadow effect renders the source with a drop shadow. The color of
868 the drop shadow can be modified using the setColor() function. The drop
869 shadow offset can be modified using the setOffset() function and the blur
870 radius of the drop shadow can be changed with the setBlurRadius()
871 function.
872
873 By default, the drop shadow is a semi-transparent dark gray
874 (QColor(63, 63, 63, 180)) shadow, blurred with a radius of 1 at an offset
875 of 8 pixels towards the lower right.
876
877 \img graphicseffect-drop-shadow.png
878
879 \sa QGraphicsBlurEffect, QGraphicsColorizeEffect, QGraphicsOpacityEffect
880*/
881
882/*!
883 Constructs a new QGraphicsDropShadowEffect instance.
884 The \a parent parameter is passed to QGraphicsEffect's constructor.
885*/
886QGraphicsDropShadowEffect::QGraphicsDropShadowEffect(QObject *parent)
887 : QGraphicsEffect(*new QGraphicsDropShadowEffectPrivate, parent)
888{
889}
890
891/*!
892 Destroys the effect.
893*/
894QGraphicsDropShadowEffect::~QGraphicsDropShadowEffect()
895{
896}
897
898/*!
899 \property QGraphicsDropShadowEffect::offset
900 \brief the shadow offset in pixels.
901
902 By default, the offset is 8 pixels towards the lower right.
903
904 \sa xOffset(), yOffset(), blurRadius(), color()
905*/
906QPointF QGraphicsDropShadowEffect::offset() const
907{
908 Q_D(const QGraphicsDropShadowEffect);
909 return d->filter->offset();
910}
911
912void QGraphicsDropShadowEffect::setOffset(const QPointF &offset)
913{
914 Q_D(QGraphicsDropShadowEffect);
915 if (d->filter->offset() == offset)
916 return;
917
918 d->filter->setOffset(offset);
919 updateBoundingRect();
920 emit offsetChanged(offset);
921}
922
923/*!
924 \property QGraphicsDropShadowEffect::xOffset
925 \brief the horizontal shadow offset in pixels.
926
927 By default, the horizontal shadow offset is 8 pixels.
928
929
930
931 \sa yOffset(), offset()
932*/
933
934/*!
935 \property QGraphicsDropShadowEffect::yOffset
936 \brief the vertical shadow offset in pixels.
937
938 By default, the vertical shadow offset is 8 pixels.
939
940 \sa xOffset(), offset()
941*/
942
943/*!
944 \fn void QGraphicsDropShadowEffect::offsetChanged(const QPointF &offset)
945
946 This signal is emitted whenever the effect's shadow offset changes.
947 The \a offset parameter holds the effect's new shadow offset.
948*/
949
950/*!
951 \property QGraphicsDropShadowEffect::blurRadius
952 \brief the blur radius in pixels of the drop shadow.
953
954 Using a smaller radius results in a sharper shadow, whereas using a bigger
955 radius results in a more blurred shadow.
956
957 By default, the blur radius is 1 pixel.
958
959 \sa color(), offset().
960*/
961qreal QGraphicsDropShadowEffect::blurRadius() const
962{
963 Q_D(const QGraphicsDropShadowEffect);
964 return d->filter->blurRadius();
965}
966
967void QGraphicsDropShadowEffect::setBlurRadius(qreal blurRadius)
968{
969 Q_D(QGraphicsDropShadowEffect);
970 if (qFuzzyCompare(d->filter->blurRadius(), blurRadius))
971 return;
972
973 d->filter->setBlurRadius(blurRadius);
974 updateBoundingRect();
975 emit blurRadiusChanged(blurRadius);
976}
977
978/*!
979 \fn void QGraphicsDropShadowEffect::blurRadiusChanged(qreal blurRadius)
980
981 This signal is emitted whenever the effect's blur radius changes.
982 The \a blurRadius parameter holds the effect's new blur radius.
983*/
984
985/*!
986 \property QGraphicsDropShadowEffect::color
987 \brief the color of the drop shadow.
988
989 By default, the drop color is a semi-transparent dark gray
990 (QColor(63, 63, 63, 180)).
991
992 \sa offset(), blurRadius()
993*/
994QColor QGraphicsDropShadowEffect::color() const
995{
996 Q_D(const QGraphicsDropShadowEffect);
997 return d->filter->color();
998}
999
1000void QGraphicsDropShadowEffect::setColor(const QColor &color)
1001{
1002 Q_D(QGraphicsDropShadowEffect);
1003 if (d->filter->color() == color)
1004 return;
1005
1006 d->filter->setColor(color);
1007 update();
1008 emit colorChanged(color);
1009}
1010
1011/*!
1012 \fn void QGraphicsDropShadowEffect::colorChanged(const QColor &color)
1013
1014 This signal is emitted whenever the effect's color changes.
1015 The \a color parameter holds the effect's new color.
1016*/
1017
1018/*!
1019 \reimp
1020*/
1021QRectF QGraphicsDropShadowEffect::boundingRectFor(const QRectF &rect) const
1022{
1023 Q_D(const QGraphicsDropShadowEffect);
1024 return d->filter->boundingRectFor(rect);
1025}
1026
1027/*!
1028 \reimp
1029*/
1030void QGraphicsDropShadowEffect::draw(QPainter *painter)
1031{
1032 Q_D(QGraphicsDropShadowEffect);
1033 if (d->filter->blurRadius() <= 0 && d->filter->offset().isNull()) {
1034 drawSource(painter);
1035 return;
1036 }
1037
1038 PixmapPadMode mode = PadToEffectiveBoundingRect;
1039 if (painter->paintEngine()->type() == QPaintEngine::OpenGL2)
1040 mode = NoPad;
1041
1042 // Draw pixmap in device coordinates to avoid pixmap scaling.
1043 QPoint offset;
1044 const QPixmap pixmap = sourcePixmap(Qt::DeviceCoordinates, &offset, mode);
1045 QTransform restoreTransform = painter->worldTransform();
1046 painter->setWorldTransform(QTransform());
1047 d->filter->draw(painter, offset, pixmap);
1048 painter->setWorldTransform(restoreTransform);
1049}
1050
1051/*!
1052 \class QGraphicsOpacityEffect
1053 \brief The QGraphicsOpacityEffect class provides an opacity effect.
1054 \since 4.6
1055
1056 An opacity effect renders the source with an opacity. This effect is useful
1057 for making the source semi-transparent, similar to a fade-in/fade-out
1058 sequence. The opacity can be modified using the setOpacity() function.
1059
1060 By default, the opacity is 0.7.
1061
1062 \img graphicseffect-opacity.png
1063
1064 \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsColorizeEffect
1065*/
1066
1067/*!
1068 Constructs a new QGraphicsOpacityEffect instance.
1069 The \a parent parameter is passed to QGraphicsEffect's constructor.
1070*/
1071QGraphicsOpacityEffect::QGraphicsOpacityEffect(QObject *parent)
1072 : QGraphicsEffect(*new QGraphicsOpacityEffectPrivate, parent)
1073{
1074}
1075
1076/*!
1077 Destroys the effect.
1078*/
1079QGraphicsOpacityEffect::~QGraphicsOpacityEffect()
1080{
1081}
1082
1083/*!
1084 \property QGraphicsOpacityEffect::opacity
1085 \brief the opacity of the effect.
1086
1087 The value should be in the range of 0.0 to 1.0, where 0.0 is
1088 fully transparent and 1.0 is fully opaque.
1089
1090 By default, the opacity is 0.7.
1091
1092 \sa setOpacityMask()
1093*/
1094qreal QGraphicsOpacityEffect::opacity() const
1095{
1096 Q_D(const QGraphicsOpacityEffect);
1097 return d->opacity;
1098}
1099
1100void QGraphicsOpacityEffect::setOpacity(qreal opacity)
1101{
1102 Q_D(QGraphicsOpacityEffect);
1103 opacity = qBound(qreal(0.0), opacity, qreal(1.0));
1104
1105 if (qFuzzyCompare(d->opacity, opacity))
1106 return;
1107
1108 d->opacity = opacity;
1109 if ((d->isFullyTransparent = qFuzzyIsNull(d->opacity)))
1110 d->isFullyOpaque = 0;
1111 else
1112 d->isFullyOpaque = qFuzzyIsNull(d->opacity - 1);
1113 update();
1114 emit opacityChanged(opacity);
1115}
1116
1117/*!
1118 \fn void QGraphicsOpacityEffect::opacityChanged(qreal opacity)
1119
1120 This signal is emitted whenever the effect's opacity changes.
1121 The \a opacity parameter holds the effect's new opacity.
1122*/
1123
1124/*!
1125 \property QGraphicsOpacityEffect::opacityMask
1126 \brief the opacity mask of the effect.
1127
1128 An opacity mask allows you apply opacity to portions of an element.
1129
1130 For example:
1131
1132 \snippet doc/src/snippets/code/src_gui_effects_qgraphicseffect.cpp 2
1133
1134 There is no opacity mask by default.
1135
1136 \sa setOpacity()
1137*/
1138QBrush QGraphicsOpacityEffect::opacityMask() const
1139{
1140 Q_D(const QGraphicsOpacityEffect);
1141 return d->opacityMask;
1142}
1143
1144void QGraphicsOpacityEffect::setOpacityMask(const QBrush &mask)
1145{
1146 Q_D(QGraphicsOpacityEffect);
1147 if (d->opacityMask == mask)
1148 return;
1149
1150 d->opacityMask = mask;
1151 d->hasOpacityMask = (mask.style() != Qt::NoBrush);
1152 update();
1153
1154 emit opacityMaskChanged(mask);
1155}
1156
1157/*!
1158 \fn void QGraphicsOpacityEffect::opacityMaskChanged(const QBrush &mask)
1159
1160 This signal is emitted whenever the effect's opacity mask changes.
1161 The \a mask parameter holds the effect's new opacity mask.
1162*/
1163
1164/*!
1165 \reimp
1166*/
1167void QGraphicsOpacityEffect::draw(QPainter *painter)
1168{
1169 Q_D(QGraphicsOpacityEffect);
1170
1171 // Transparent; nothing to draw.
1172 if (d->isFullyTransparent)
1173 return;
1174
1175 // Opaque; draw directly without going through a pixmap.
1176 if (d->isFullyOpaque && !d->hasOpacityMask) {
1177 drawSource(painter);
1178 return;
1179 }
1180
1181 QPoint offset;
1182 Qt::CoordinateSystem system = sourceIsPixmap() ? Qt::LogicalCoordinates : Qt::DeviceCoordinates;
1183 QPixmap pixmap = sourcePixmap(system, &offset, QGraphicsEffect::NoPad);
1184 if (pixmap.isNull())
1185 return;
1186
1187 painter->save();
1188 painter->setOpacity(d->opacity);
1189
1190 if (d->hasOpacityMask) {
1191 QPainter pixmapPainter(&pixmap);
1192 pixmapPainter.setRenderHints(painter->renderHints());
1193 pixmapPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
1194 if (system == Qt::DeviceCoordinates) {
1195 QTransform worldTransform = painter->worldTransform();
1196 worldTransform *= QTransform::fromTranslate(-offset.x(), -offset.y());
1197 pixmapPainter.setWorldTransform(worldTransform);
1198 pixmapPainter.fillRect(sourceBoundingRect(), d->opacityMask);
1199 } else {
1200 pixmapPainter.translate(-offset);
1201 pixmapPainter.fillRect(pixmap.rect(), d->opacityMask);
1202 }
1203 }
1204
1205 if (system == Qt::DeviceCoordinates)
1206 painter->setWorldTransform(QTransform());
1207
1208 painter->drawPixmap(offset, pixmap);
1209 painter->restore();
1210}
1211
1212
1213QT_END_NAMESPACE
1214
1215#endif //QT_NO_GRAPHICSEFFECT
Note: See TracBrowser for help on using the repository browser.