00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "kfadewidgeteffect.h"
00023 #include "kfadewidgeteffect_p.h"
00024
00025 #include <config.h>
00026
00027 #include <QtCore/QEvent>
00028 #include <QtGui/QPaintEngine>
00029 #include <QtGui/QPainter>
00030
00031 #include <kglobalsettings.h>
00032
00033 #if defined(Q_WS_X11) && defined(HAVE_XRENDER)
00034 # include <X11/Xlib.h>
00035 # include <X11/extensions/Xrender.h>
00036 # include <QX11Info>
00037 # undef KeyPress
00038 # undef FocusOut
00039 #endif
00040
00041 KFadeWidgetEffectPrivate::KFadeWidgetEffectPrivate(QWidget *_destWidget)
00042 : destWidget(_destWidget), disabled(false)
00043 {
00044 }
00045
00046
00047
00048
00049
00050 QPixmap KFadeWidgetEffectPrivate::transition(const QPixmap &from, const QPixmap &to, qreal amount) const
00051 {
00052 const int value = int(0xff * amount);
00053
00054 if (value == 0)
00055 return from;
00056
00057 if (value == 1)
00058 return to;
00059
00060 QColor color;
00061 color.setAlphaF(amount);
00062
00063
00064 if (from.paintEngine()->hasFeature(QPaintEngine::PorterDuff) &&
00065 from.paintEngine()->hasFeature(QPaintEngine::BlendModes))
00066 {
00067 QPixmap under = from;
00068 QPixmap over = to;
00069
00070 QPainter p;
00071 p.begin(&over);
00072 p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
00073 p.fillRect(over.rect(), color);
00074 p.end();
00075
00076 p.begin(&under);
00077 p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
00078 p.fillRect(under.rect(), color);
00079 p.setCompositionMode(QPainter::CompositionMode_Plus);
00080 p.drawPixmap(0, 0, over);
00081 p.end();
00082
00083 return under;
00084 }
00085 #if defined(Q_WS_X11) && defined(HAVE_XRENDER)
00086 else if (from.paintEngine()->hasFeature(QPaintEngine::PorterDuff))
00087 {
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 QPixmap source(to), destination(from);
00100
00101 source.detach();
00102 destination.detach();
00103
00104 Display *dpy = QX11Info::display();
00105
00106 XRenderPictFormat *format = XRenderFindStandardFormat(dpy, PictStandardA8);
00107 XRenderPictureAttributes pa;
00108 pa.repeat = 1;
00109
00110
00111 Pixmap pixmap = XCreatePixmap(dpy, destination.handle(), 1, 1, 8);
00112 Picture alpha = XRenderCreatePicture(dpy, pixmap, format, CPRepeat, &pa);
00113 XFreePixmap(dpy, pixmap);
00114
00115
00116 XRenderColor xcolor;
00117 xcolor.alpha = quint16(0xffff * amount);
00118 XRenderFillRectangle(dpy, PictOpSrc, alpha, &xcolor, 0, 0, 1, 1);
00119
00120
00121 XRenderComposite(dpy, PictOpOutReverse, alpha, None, destination.x11PictureHandle(),
00122 0, 0, 0, 0, 0, 0, destination.width(), destination.height());
00123
00124
00125 XRenderComposite(dpy, PictOpAdd, source.x11PictureHandle(), alpha,
00126 destination.x11PictureHandle(),
00127 0, 0, 0, 0, 0, 0, destination.width(), destination.height());
00128
00129 XRenderFreePicture(dpy, alpha);
00130 return destination;
00131 }
00132 #endif
00133 else
00134 {
00135
00136 QImage under = from.toImage();
00137 QImage over = to.toImage();
00138
00139 QPainter p;
00140 p.begin(&over);
00141 p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
00142 p.fillRect(over.rect(), color);
00143 p.end();
00144
00145 p.begin(&under);
00146 p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
00147 p.fillRect(under.rect(), color);
00148 p.setCompositionMode(QPainter::CompositionMode_Plus);
00149 p.drawImage(0, 0, over);
00150 p.end();
00151
00152 return QPixmap::fromImage(under);
00153 }
00154 }
00155
00156 KFadeWidgetEffect::KFadeWidgetEffect(QWidget *destWidget)
00157 : QWidget(destWidget ? destWidget->parentWidget() : 0),
00158 d_ptr(new KFadeWidgetEffectPrivate(destWidget))
00159 {
00160 Q_D(KFadeWidgetEffect);
00161 d->q_ptr = this;
00162 Q_ASSERT(destWidget && destWidget->parentWidget());
00163 if (!destWidget || !destWidget->parentWidget() || !destWidget->isVisible() ||
00164 !(KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects)) {
00165 d->disabled = true;
00166 hide();
00167 return;
00168 }
00169 setGeometry(QRect(destWidget->mapTo(parentWidget(), QPoint(0, 0)), destWidget->size()));
00170 d->oldPixmap = QPixmap::grabWidget(destWidget);
00171 d->timeLine.setFrameRange(0, 255);
00172 d->timeLine.setCurveShape(QTimeLine::EaseOutCurve);
00173 connect(&d->timeLine, SIGNAL(finished()), SLOT(finished()));
00174 connect(&d->timeLine, SIGNAL(frameChanged(int)), SLOT(repaint()));
00175 show();
00176 }
00177
00178 KFadeWidgetEffect::~KFadeWidgetEffect()
00179 {
00180 delete d_ptr;
00181 }
00182
00183 void KFadeWidgetEffectPrivate::finished()
00184 {
00185 Q_Q(KFadeWidgetEffect);
00186 destWidget->setUpdatesEnabled(false);
00187 q->hide();
00188 q->deleteLater();
00189 destWidget->setUpdatesEnabled(true);
00190 }
00191
00192 void KFadeWidgetEffect::start(int duration)
00193 {
00194 Q_D(KFadeWidgetEffect);
00195 if (d->disabled) {
00196 deleteLater();
00197 return;
00198 }
00199 d->newPixmap = QPixmap::grabWidget(d->destWidget);
00200 d->timeLine.setDuration(duration);
00201 d->timeLine.start();
00202 }
00203
00204 void KFadeWidgetEffect::paintEvent(QPaintEvent *)
00205 {
00206 Q_D(KFadeWidgetEffect);
00207 QPainter p(this);
00208 p.drawPixmap(rect(), d->transition(d->oldPixmap, d->newPixmap, d->timeLine.currentValue()));
00209 p.end();
00210 }
00211
00212 #include "moc_kfadewidgeteffect.cpp"