• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

parley

  • sources
  • kde-4.14
  • kdeedu
  • parley
  • src
  • practice
imagewidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  Copyright 2009 Daniel Laidig <d.laidig@gmx.de>
3  ***************************************************************************/
4 
5 /***************************************************************************
6  * *
7  * This program is free software; you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation; either version 2 of the License, or *
10  * (at your option) any later version. *
11  * *
12  ***************************************************************************/
13 
14 #include "imagewidget.h"
15 #include "../config-parley.h"
16 
17 #include <QtGui/QPainter>
18 #include <QtGui/QPaintEngine>
19 #include <QtCore/QTimer>
20 #include <QtCore/QTimeLine>
21 
22 #include <kdebug.h>
23 
24 #if defined(Q_WS_X11) && defined(HAVE_XRENDER)
25 #include <X11/Xlib.h>
26 #include <X11/extensions/Xrender.h>
27 #include <QX11Info>
28 #undef KeyPress
29 #undef FocusOut
30 #endif
31 
32 using namespace Practice;
33 
34 // The functions centerPixmaps() and transition() are copied from kdelibs/plasma/paintutils.cpp, revision 1133527
35 // License: LGPLv2+
36 // Copyright 2005 by Aaron Seigo <aseigo@kde.org>
37 // Copyright 2008 by Andrew Lake <jamboarder@yahoo.com>
38 // Don't just modify the code here, if there are issues they should probably also be fixed in libplasma.
39 
40 void centerPixmaps(QPixmap &from, QPixmap &to)
41 {
42  if (from.size() == to.size() && from.hasAlphaChannel() && to.hasAlphaChannel()) {
43  return;
44  }
45  QRect fromRect(from.rect());
46  QRect toRect(to.rect());
47 
48  QRect actualRect = QRect(QPoint(0, 0), fromRect.size().expandedTo(toRect.size()));
49  fromRect.moveCenter(actualRect.center());
50  toRect.moveCenter(actualRect.center());
51 
52  if (from.size() != actualRect.size() || !from.hasAlphaChannel()) {
53  QPixmap result(actualRect.size());
54  result.fill(Qt::transparent);
55  QPainter p(&result);
56  p.setCompositionMode(QPainter::CompositionMode_Source);
57  p.drawPixmap(fromRect.topLeft(), from);
58  p.end();
59  from = result;
60  }
61 
62  if (to.size() != actualRect.size() || !to.hasAlphaChannel()) {
63  QPixmap result(actualRect.size());
64  result.fill(Qt::transparent);
65  QPainter p(&result);
66  p.setCompositionMode(QPainter::CompositionMode_Source);
67  p.drawPixmap(toRect.topLeft(), to);
68  p.end();
69  to = result;
70  }
71 }
72 
73 QPixmap transition(const QPixmap &from, const QPixmap &to, qreal amount)
74 {
75  if (from.isNull() && to.isNull()) {
76  return from;
77  }
78 
79  QPixmap startPixmap(from);
80  QPixmap targetPixmap(to);
81 
82  if (from.size() != to.size() || !from.hasAlphaChannel() || !to.hasAlphaChannel()) {
83  centerPixmaps(startPixmap, targetPixmap);
84  }
85 
86  //paint to in the center of from
87  QRect toRect = to.rect();
88 
89  QColor color;
90  color.setAlphaF(amount);
91 
92 
93  // If the native paint engine supports Porter/Duff compositing and CompositionMode_Plus
94  QPaintEngine *paintEngine = from.paintEngine();
95  if (paintEngine &&
96  paintEngine->hasFeature(QPaintEngine::PorterDuff) &&
97  paintEngine->hasFeature(QPaintEngine::BlendModes)) {
98 
99  QPainter p;
100  p.begin(&targetPixmap);
101  p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
102  p.fillRect(targetPixmap.rect(), color);
103  p.end();
104 
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);
110  p.end();
111 
112  return startPixmap;
113  }
114 #if defined(Q_WS_X11) && defined(HAVE_XRENDER)
115  // We have Xrender support
116  else if (paintEngine && paintEngine->hasFeature(QPaintEngine::PorterDuff)) {
117  // QX11PaintEngine doesn't implement CompositionMode_Plus in Qt 4.3,
118  // which we need to be able to do a transition from one pixmap to
119  // another.
120  //
121  // In order to avoid the overhead of converting the pixmaps to images
122  // and doing the operation entirely in software, this function has a
123  // specialized path for X11 that uses Xrender directly to do the
124  // transition. This operation can be fully accelerated in HW.
125  //
126  // This specialization can be removed when QX11PaintEngine supports
127  // CompositionMode_Plus.
128  QPixmap source(targetPixmap), destination(startPixmap);
129 
130  source.detach();
131  destination.detach();
132 
133  Display *dpy = QX11Info::display();
134 
135  XRenderPictFormat *format = XRenderFindStandardFormat(dpy, PictStandardA8);
136  XRenderPictureAttributes pa;
137  pa.repeat = 1; // RepeatNormal
138 
139  // Create a 1x1 8 bit repeating alpha picture
140  Pixmap pixmap = XCreatePixmap(dpy, destination.handle(), 1, 1, 8);
141  Picture alpha = XRenderCreatePicture(dpy, pixmap, format, CPRepeat, &pa);
142  XFreePixmap(dpy, pixmap);
143 
144  // Fill the alpha picture with the opacity value
145  XRenderColor xcolor;
146  xcolor.alpha = quint16(0xffff * amount);
147  XRenderFillRectangle(dpy, PictOpSrc, alpha, &xcolor, 0, 0, 1, 1);
148 
149  // Reduce the alpha of the destination with 1 - opacity
150  XRenderComposite(dpy, PictOpOutReverse, alpha, None, destination.x11PictureHandle(),
151  0, 0, 0, 0, 0, 0, destination.width(), destination.height());
152 
153  // Add source * opacity to the destination
154  XRenderComposite(dpy, PictOpAdd, source.x11PictureHandle(), alpha,
155  destination.x11PictureHandle(),
156  toRect.x(), toRect.y(), 0, 0, 0, 0, destination.width(), destination.height());
157 
158  XRenderFreePicture(dpy, alpha);
159  return destination;
160  }
161 #endif
162  else {
163  // Fall back to using QRasterPaintEngine to do the transition.
164  QImage under = startPixmap.toImage();
165  QImage over = targetPixmap.toImage();
166 
167  QPainter p;
168  p.begin(&over);
169  p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
170  p.fillRect(over.rect(), color);
171  p.end();
172 
173  p.begin(&under);
174  p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
175  p.fillRect(under.rect(), color);
176  p.setCompositionMode(QPainter::CompositionMode_Plus);
177  p.drawImage(toRect.topLeft(), over);
178  p.end();
179 
180  return QPixmap::fromImage(under);
181  }
182 }
183 
184 
185 ImageWidget::ImageWidget(QWidget *parent)
186  : QWidget(parent), m_fading(true), m_scaling(true), m_onlyDownscaling(true), m_keepAspectRatio(Qt::KeepAspectRatio), m_alignment(Qt::AlignCenter)
187 {
188  m_scaleTimer = new QTimer(this);
189  m_scaleTimer->setSingleShot(true);
190  m_scaleTimer->setInterval(500);
191 
192  m_animation = new QTimeLine(300, this);
193 
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()));
198 }
199 
200 void ImageWidget::setPixmap(const QPixmap& pixmap)
201 {
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());
205  m_animation->stop();
206  animationFinished();
207  }
208 
209  m_animationPixmap = m_scaledPixmap;
210  m_originalPixmap = pixmap;
211  m_scaledPixmap = QPixmap();
212  m_scaledBackupPixmap = QPixmap();
213  m_scaledPixmapOutOfDate = true;
214  if (!m_scaling) {
215  m_scaledPixmap = pixmap;
216  }
217  scalePixmap(true);
218  if (m_fading) {
219  m_animation->start();
220  }
221  update();
222 }
223 
224 void ImageWidget::setScalingEnabled(bool scaling, bool onlyDownscaling)
225 {
226  m_scaling = scaling;
227  m_onlyDownscaling = onlyDownscaling;
228 }
229 
230 void ImageWidget::setKeepAspectRatio(Qt::AspectRatioMode mode)
231 {
232  m_keepAspectRatio = mode;
233 }
234 
235 void ImageWidget::setFadingEnabled(bool fading)
236 {
237  m_fading = fading;
238 }
239 
240 void ImageWidget::setAlignment(Qt::Alignment alignment)
241 {
242  m_alignment = alignment;
243 }
244 
245 void ImageWidget::paintEvent(QPaintEvent* e)
246 {
247  QWidget::paintEvent(e);
248  QPainter painter(this);
249  if (m_scaling && m_scaledPixmapOutOfDate) {
250  m_scaleTimer->start();
251  scalePixmap(false);
252  }
253  QPixmap pm = m_scaledPixmap;
254  if (m_animation->state() == QTimeLine::Running) {
255  pm = transition(m_animationPixmap, m_scaledPixmap, m_animation->currentValue());
256  }
257 
258  int x = (size().width() - pm.width()) / 2;
259  if (m_alignment.testFlag(Qt::AlignLeft)) {
260  x = 0;
261  } else if (m_alignment.testFlag(Qt::AlignRight)) {
262  x = size().width() - pm.width();
263  }
264  int y = (size().height() - pm.height()) / 2;
265  if (m_alignment.testFlag(Qt::AlignTop)) {
266  y = 0;
267  } else if (m_alignment.testFlag(Qt::AlignBottom)) {
268  y = size().height() - pm.height();
269  }
270  painter.drawPixmap(x, y, pm);
271 }
272 
273 void ImageWidget::resizeEvent(QResizeEvent* e)
274 {
275  if (!m_scaledPixmapOutOfDate) {
276  m_scaledBackupPixmap = m_scaledPixmap;
277  }
278  // stop animations when resizing
279  if (m_animation->state() == QTimeLine::Running) {
280  m_animation->stop();
281  animationFinished();
282  }
283  m_scaledPixmapOutOfDate = true;
284  QWidget::resizeEvent(e);
285  emit sizeChanged();
286 }
287 
288 void ImageWidget::scalePixmap(bool smooth)
289 {
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();
296  } else if (smooth) {
297  //kDebug() << "smooth scaling to" << size();
298  if (m_originalPixmap.isNull() || size().isEmpty()) {
299  m_scaledPixmapOutOfDate = false;
300  m_scaledPixmap = QPixmap();
301  update();
302  return;
303  }
304  m_scaledPixmap = m_originalPixmap.scaled(size(), m_keepAspectRatio, Qt::SmoothTransformation);
305  m_scaledBackupPixmap = QPixmap();
306  m_scaledPixmapOutOfDate = false;
307  update();
308  } else {
309  //kDebug() << "fast scaling to" << size();
310  // Try to find out if it makes sense to use the scaled backup pixmap.
311  // If the scaled backup gets too small, we use the original image.
312  float ratio = 0;
313  if (!size().isEmpty()) {
314  ratio = qMin(float(m_scaledBackupPixmap.width()) / size().width(),
315  float(m_scaledBackupPixmap.height()) / size().height());
316  }
317  if (ratio > 0.4 && !m_scaledBackupPixmap.isNull()) {
318  m_scaledPixmap = m_scaledBackupPixmap.scaled(size(), m_keepAspectRatio, Qt::FastTransformation);
319  } else {
320  if (m_originalPixmap.isNull() || size().isEmpty()) {
321  m_scaledPixmap = QPixmap();
322  return;
323  }
324  // use the original pixmap
325  m_scaledPixmap = m_originalPixmap.scaled(size(), m_keepAspectRatio, Qt::FastTransformation);
326  m_scaledBackupPixmap = m_scaledPixmap;
327  }
328  m_scaledPixmapOutOfDate = true;
329  }
330 }
331 
332 void ImageWidget::animationFinished()
333 {
334  m_animationPixmap = QPixmap();
335 }
336 
337 #include "imagewidget.moc"
QTimer::setInterval
void setInterval(int msec)
QPixmap::detach
void detach()
QPaintEngine
QPixmap::size
QSize size() const
QResizeEvent
QWidget
QSize::width
int width() const
Practice::ImageWidget::ImageWidget
ImageWidget(QWidget *parent=0)
Definition: imagewidget.cpp:185
QPixmap::width
int width() const
QPainter::end
bool end()
QPainter::fillRect
void fillRect(const QRectF &rectangle, const QBrush &brush)
QPainter::setCompositionMode
void setCompositionMode(CompositionMode mode)
QPixmap::fill
void fill(const QColor &color)
QSize::isEmpty
bool isEmpty() const
Practice::ImageWidget::paintEvent
virtual void paintEvent(QPaintEvent *e)
Definition: imagewidget.cpp:245
QX11Info::display
Display * display()
QWidget::y
int y() const
QPixmap::fromImage
QPixmap fromImage(const QImage &image, QFlags< Qt::ImageConversionFlag > flags)
QRect::x
int x() const
QRect::y
int y() const
QPoint
transition
QPixmap transition(const QPixmap &from, const QPixmap &to, qreal amount)
Definition: imagewidget.cpp:73
Practice::ImageWidget::setAlignment
void setAlignment(Qt::Alignment alignment)
Definition: imagewidget.cpp:240
QPaintDevice::paintEngine
virtual QPaintEngine * paintEngine() const =0
Qt::Alignment
typedef Alignment
QPixmap::hasAlphaChannel
bool hasAlphaChannel() const
QWidget::update
void update()
Practice::ImageWidget::setScalingEnabled
void setScalingEnabled(bool scaling, bool onlyDownscaling=true)
Definition: imagewidget.cpp:224
QWidget::size
QSize size() const
QRect
Practice::ImageWidget::resizeEvent
virtual void resizeEvent(QResizeEvent *e)
Definition: imagewidget.cpp:273
QWidget::paintEvent
virtual void paintEvent(QPaintEvent *event)
Practice::ImageWidget::setKeepAspectRatio
void setKeepAspectRatio(Qt::AspectRatioMode mode)
Definition: imagewidget.cpp:230
QTimer
QWidget::x
int x() const
QPainter::drawPixmap
void drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
QPainter
QImage::rect
QRect rect() const
QTimeLine::currentValue
qreal currentValue() const
Practice::ImageWidget::setPixmap
void setPixmap(const QPixmap &pixmap)
Definition: imagewidget.cpp:200
QPixmap::handle
Qt::HANDLE handle() const
QPixmap::scaled
QPixmap scaled(int width, int height, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformMode) const
QColor
QPixmap
QPixmap::isNull
bool isNull() const
QPixmap::height
int height() const
QImage
centerPixmaps
void centerPixmaps(QPixmap &from, QPixmap &to)
Definition: imagewidget.cpp:40
QPainter::drawImage
void drawImage(const QRectF &target, const QImage &image, const QRectF &source, QFlags< Qt::ImageConversionFlag > flags)
QPixmap::x11PictureHandle
Qt::HANDLE x11PictureHandle() const
QSize::height
int height() const
QTimeLine::stop
void stop()
imagewidget.h
QRect::topLeft
QPoint topLeft() const
QTimeLine
QTimer::start
void start(int msec)
Practice::ImageWidget::setFadingEnabled
void setFadingEnabled(bool fading)
Definition: imagewidget.cpp:235
QColor::setAlphaF
void setAlphaF(qreal alpha)
QPaintEngine::hasFeature
bool hasFeature(QFlags< QPaintEngine::PaintEngineFeature > feature) const
QPixmap::toImage
QImage toImage() const
QPaintEvent
QWidget::resizeEvent
virtual void resizeEvent(QResizeEvent *event)
Practice::ImageWidget::sizeChanged
void sizeChanged()
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QPainter::begin
bool begin(QPaintDevice *device)
QPixmap::rect
QRect rect() const
QTimeLine::start
void start()
QTimeLine::state
State state() const
QTimer::setSingleShot
void setSingleShot(bool singleShot)
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:15:56 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

parley

Skip menu "parley"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal