15 #include "../config-parley.h"
17 #include <QtGui/QPainter>
18 #include <QtGui/QPaintEngine>
19 #include <QtCore/QTimer>
20 #include <QtCore/QTimeLine>
24 #if defined(Q_WS_X11) && defined(HAVE_XRENDER)
26 #include <X11/extensions/Xrender.h>
32 using namespace Practice;
42 if (from.size() == to.size() && from.hasAlphaChannel() && to.hasAlphaChannel()) {
45 QRect fromRect(from.rect());
46 QRect toRect(to.rect());
48 QRect actualRect = QRect(QPoint(0,0), fromRect.size().expandedTo(toRect.size()));
49 fromRect.moveCenter(actualRect.center());
50 toRect.moveCenter(actualRect.center());
52 if (from.size() != actualRect.size() || !from.hasAlphaChannel()) {
53 QPixmap result(actualRect.size());
54 result.fill(Qt::transparent);
56 p.setCompositionMode(QPainter::CompositionMode_Source);
57 p.drawPixmap(fromRect.topLeft(), from);
62 if (to.size() != actualRect.size() || !to.hasAlphaChannel()) {
63 QPixmap result(actualRect.size());
64 result.fill(Qt::transparent);
66 p.setCompositionMode(QPainter::CompositionMode_Source);
67 p.drawPixmap(toRect.topLeft(), to);
73 QPixmap
transition(
const QPixmap &from,
const QPixmap &to, qreal amount)
75 if (from.isNull() && to.isNull()) {
79 QPixmap startPixmap(from);
80 QPixmap targetPixmap(to);
82 if (from.size() != to.size() || !from.hasAlphaChannel() || !to.hasAlphaChannel()) {
87 QRect toRect = to.rect();
90 color.setAlphaF(amount);
94 QPaintEngine *paintEngine = from.paintEngine();
96 paintEngine->hasFeature(QPaintEngine::PorterDuff) &&
97 paintEngine->hasFeature(QPaintEngine::BlendModes)) {
100 p.begin(&targetPixmap);
101 p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
102 p.fillRect(targetPixmap.rect(), color);
105 p.begin(&startPixmap);
106 p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
107 p.fillRect(startPixmap.rect(), color);
108 p.setCompositionMode(QPainter::CompositionMode_Plus);
109 p.drawPixmap(toRect.topLeft(), targetPixmap);
114 #if defined(Q_WS_X11) && defined(HAVE_XRENDER)
116 else if (paintEngine && paintEngine->hasFeature(QPaintEngine::PorterDuff)) {
128 QPixmap source(targetPixmap), destination(startPixmap);
131 destination.detach();
133 Display *dpy = QX11Info::display();
135 XRenderPictFormat *format = XRenderFindStandardFormat(dpy, PictStandardA8);
136 XRenderPictureAttributes pa;
140 Pixmap pixmap = XCreatePixmap(dpy, destination.handle(), 1, 1, 8);
141 Picture alpha = XRenderCreatePicture(dpy, pixmap, format, CPRepeat, &pa);
142 XFreePixmap(dpy, pixmap);
146 xcolor.alpha = quint16(0xffff * amount);
147 XRenderFillRectangle(dpy, PictOpSrc, alpha, &xcolor, 0, 0, 1, 1);
150 XRenderComposite(dpy, PictOpOutReverse, alpha, None, destination.x11PictureHandle(),
151 0, 0, 0, 0, 0, 0, destination.width(), destination.height());
154 XRenderComposite(dpy, PictOpAdd, source.x11PictureHandle(), alpha,
155 destination.x11PictureHandle(),
156 toRect.x(), toRect.y(), 0, 0, 0, 0, destination.width(), destination.height());
158 XRenderFreePicture(dpy, alpha);
164 QImage under = startPixmap.toImage();
165 QImage over = targetPixmap.toImage();
169 p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
170 p.fillRect(over.rect(), color);
174 p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
175 p.fillRect(under.rect(), color);
176 p.setCompositionMode(QPainter::CompositionMode_Plus);
177 p.drawImage(toRect.topLeft(), over);
180 return QPixmap::fromImage(under);
186 :
QWidget(parent), m_fading(true), m_scaling(true), m_onlyDownscaling(true), m_keepAspectRatio(Qt::KeepAspectRatio), m_alignment(Qt::AlignCenter)
188 m_scaleTimer =
new QTimer(
this);
189 m_scaleTimer->setSingleShot(
true);
190 m_scaleTimer->setInterval(500);
192 m_animation =
new QTimeLine(300,
this);
194 m_scaledPixmapOutOfDate =
false;
195 connect(m_scaleTimer, SIGNAL(timeout()),
this, SLOT(scalePixmap()));
196 connect(m_animation, SIGNAL(valueChanged(qreal)),
this, SLOT(update()));
197 connect(m_animation, SIGNAL(finished()),
this, SLOT(animationFinished()));
202 kDebug() <<
"set new pixmap, size:" << pixmap.size();
203 if (m_animation->state() == QTimeLine::Running) {
204 m_scaledPixmap =
transition(m_animationPixmap, m_scaledPixmap, m_animation->currentValue());
209 m_animationPixmap = m_scaledPixmap;
210 m_originalPixmap = pixmap;
211 m_scaledPixmap = QPixmap();
212 m_scaledBackupPixmap = QPixmap();
213 m_scaledPixmapOutOfDate =
true;
215 m_scaledPixmap = pixmap;
219 m_animation->start();
227 m_onlyDownscaling = onlyDownscaling;
232 m_keepAspectRatio = mode;
242 m_alignment = alignment;
247 QWidget::paintEvent(e);
248 QPainter painter(
this);
249 if (m_scaling && m_scaledPixmapOutOfDate) {
250 m_scaleTimer->start();
253 QPixmap pm = m_scaledPixmap;
254 if (m_animation->state() == QTimeLine::Running) {
255 pm =
transition(m_animationPixmap, m_scaledPixmap, m_animation->currentValue());
258 int x = (size().width() - pm.width()) / 2;
259 if (m_alignment.testFlag(Qt::AlignLeft)) {
261 }
else if (m_alignment.testFlag(Qt::AlignRight)) {
262 x = size().width() - pm.width();
264 int y = (size().height() - pm.height()) / 2;
265 if (m_alignment.testFlag(Qt::AlignTop)) {
267 }
else if (m_alignment.testFlag(Qt::AlignBottom)) {
268 y = size().height() - pm.height();
270 painter.drawPixmap(x, y, pm);
275 if (!m_scaledPixmapOutOfDate) {
276 m_scaledBackupPixmap = m_scaledPixmap;
279 if (m_animation->state() == QTimeLine::Running) {
283 m_scaledPixmapOutOfDate =
true;
284 QWidget::resizeEvent(e);
288 void ImageWidget::scalePixmap(
bool smooth)
290 bool scaleUp = m_originalPixmap.width() <= size().width() && m_originalPixmap.height() <= size().height();
291 if ((m_onlyDownscaling && scaleUp) || m_originalPixmap.size() == size()) {
292 kDebug() <<
"no need to scale pixmap";
293 m_scaledPixmapOutOfDate =
false;
294 m_scaledPixmap = m_originalPixmap;
295 m_scaledBackupPixmap = QPixmap();
297 kDebug() <<
"smooth scaling to" << size();
298 if (m_originalPixmap.isNull() || size().isEmpty()) {
299 m_scaledPixmapOutOfDate =
false;
300 m_scaledPixmap = QPixmap();
304 m_scaledPixmap = m_originalPixmap.scaled(size(), m_keepAspectRatio, Qt::SmoothTransformation);
305 m_scaledBackupPixmap = QPixmap();
306 m_scaledPixmapOutOfDate =
false;
309 kDebug() <<
"fast scaling to" << size();
313 if (!size().isEmpty()) {
314 ratio = qMin(
float(m_scaledBackupPixmap.width())/size().width(),
315 float(m_scaledBackupPixmap.height())/size().height());
317 if (ratio > 0.4 && !m_scaledBackupPixmap.isNull()) {
318 m_scaledPixmap = m_scaledBackupPixmap.scaled(size(), m_keepAspectRatio, Qt::FastTransformation);
320 if (m_originalPixmap.isNull() || size().isEmpty()) {
321 m_scaledPixmap = QPixmap();
325 m_scaledPixmap = m_originalPixmap.scaled(size(), m_keepAspectRatio, Qt::FastTransformation);
326 m_scaledBackupPixmap = m_scaledPixmap;
328 m_scaledPixmapOutOfDate =
true;
332 void ImageWidget::animationFinished()
334 m_animationPixmap = QPixmap();
337 #include "imagewidget.moc"