• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

Plasma

wallpaperrenderthread.cpp

Go to the documentation of this file.
00001 /*
00002  *   Copyright (c) 2007 Paolo Capriotti <p.capriotti@gmail.com>
00003  *   Copyright (c) 2009 Aaron Seigo <aseigo@kde.org>
00004  *
00005  *   This program is free software; you can redistribute it and/or modify
00006  *   it under the terms of the GNU Library General Public License as
00007  *   published by the Free Software Foundation; either version 2, or
00008  *   (at your option) any later version.
00009  *
00010  *   This program is distributed in the hope that it will be useful,
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *   GNU General Public License for more details
00014  *
00015  *   You should have received a copy of the GNU Library General Public
00016  *   License along with this program; if not, write to the
00017  *   Free Software Foundation, Inc.,
00018  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00019  */
00020 
00021 #include "plasma/private/wallpaperrenderthread_p.h"
00022 
00023 #include <QCoreApplication>
00024 #include <QPainter>
00025 #include <QFile>
00026 #include <QSvgRenderer>
00027 
00028 #include <kdebug.h>
00029 
00030 #ifndef PLASMA_NO_SOLID
00031 #include <solid/device.h>
00032 #include <solid/deviceinterface.h>
00033 #endif
00034 
00035 namespace Plasma
00036 {
00037 
00038 int WallpaperRenderRequest::s_token = 0;
00039 int WallpaperRenderThread::s_rendererCount = 0;
00040 QQueue<WallpaperRenderRequest> WallpaperRenderThread::s_renderQueue;
00041 
00042 WallpaperRenderThread::WallpaperRenderThread(const WallpaperRenderRequest &request, QObject *parent)
00043     : QThread(parent),
00044       m_request(request),
00045       m_abort(false)
00046 {
00047     qRegisterMetaType<WallpaperRenderRequest>("WallpaperRenderRequest");
00048     if (!request.requester) {
00049         deleteLater();
00050         return;
00051     }
00052 
00053     ++s_rendererCount;
00054     connect(this, SIGNAL(done(WallpaperRenderRequest,QImage)),
00055             request.requester.data(), SLOT(newRenderCompleted(WallpaperRenderRequest,QImage)));
00056 }
00057 
00058 WallpaperRenderThread::~WallpaperRenderThread()
00059 {
00060     kDebug() << "rendering done";
00061     m_abort = true;
00062     wait();
00063     --s_rendererCount;
00064     checkQueue();
00065 }
00066 
00067 void WallpaperRenderThread::render(const WallpaperRenderRequest &request)
00068 {
00069     QObject *requester = request.requester.data();
00070     if (!requester) {
00071         return;
00072     }
00073 
00074     // remove all dead requests and requests previously made for the same parent
00075     QMutableListIterator<WallpaperRenderRequest> it(s_renderQueue);
00076     while (it.hasNext()) {
00077         const WallpaperRenderRequest &request = it.next();
00078 
00079         if (!request.requester || request.requester.data() == requester) {
00080             it.remove();
00081         }
00082     }
00083 
00084     s_renderQueue.append(request);
00085     checkQueue();
00086 }
00087 
00088 void WallpaperRenderThread::checkQueue()
00089 {
00090     if (s_renderQueue.isEmpty()) {
00091         return;
00092     }
00093 
00094     if (QCoreApplication::closingDown()) {
00095         s_renderQueue.clear();
00096         return;
00097     }
00098 
00099 #ifndef PLASMA_NO_SOLID
00100     const int numProcs = qMax(1, Solid::Device::listFromType(Solid::DeviceInterface::Processor).count());
00101 #else
00102     const int numProcs = 1;
00103 #endif
00104     kDebug() << "checking rendering against" << s_rendererCount << numProcs;
00105     if (s_rendererCount < numProcs) {
00106         WallpaperRenderThread *renderThread = new WallpaperRenderThread(s_renderQueue.dequeue());
00107         renderThread->start();
00108     }
00109 }
00110 
00111 void WallpaperRenderThread::run()
00112 {
00113     kDebug() << "rendering wallpaper" << m_request.file;
00114     QImage result(m_request.size, QImage::Format_ARGB32_Premultiplied);
00115     result.fill(m_request.color.rgba());
00116 
00117     if (m_request.file.isEmpty() || !QFile::exists(m_request.file)) {
00118         if (!m_abort) {
00119             emit done(m_request, result);
00120         }
00121 
00122         kDebug() << "oh, fuck it";
00123         deleteLater();
00124         return;
00125     }
00126 
00127     QPoint pos(0, 0);
00128     //const float ratio = qMax(float(1), m_request.size.width() / float(m_request.size.height()));
00129     const bool scalable = m_request.file.endsWith(QLatin1String("svg")) || m_request.file.endsWith(QLatin1String("svgz"));
00130     bool tiled = false;
00131     QSize scaledSize;
00132     QImage img;
00133 
00134     // set image size
00135     QSize imgSize(1, 1);
00136     if (scalable) {
00137         // scalable: image can be of any size
00138         imgSize = imgSize.expandedTo(m_request.size);
00139     } else {
00140         // otherwise, use the natural size of the loaded image
00141         img = QImage(m_request.file);
00142         imgSize = imgSize.expandedTo(img.size());
00143         //kDebug() << "loaded with" << imgSize << ratio;
00144     }
00145 
00146     // set render parameters according to resize mode
00147     switch (m_request.resizeMethod)
00148     {
00149         case Wallpaper::ScaledResize:
00150             scaledSize = m_request.size;
00151             break;
00152         case Wallpaper::CenteredResize:
00153             scaledSize = imgSize;
00154             pos = QPoint((m_request.size.width() - scaledSize.width()) / 2,
00155                          (m_request.size.height() - scaledSize.height()) / 2);
00156 
00157             //If the picture is bigger than the screen, shrink it
00158             if (m_request.size.width() < imgSize.width() && imgSize.width() > imgSize.height()) {
00159                 int width = m_request.size.width();
00160                 int height = width * scaledSize.height() / imgSize.width();
00161                 scaledSize = QSize(width, height);
00162                 pos = QPoint((m_request.size.width() - scaledSize.width()) / 2,
00163                         (m_request.size.height() - scaledSize.height()) / 2);
00164             } else if (m_request.size.height() < imgSize.height()) {
00165                 int height = m_request.size.height();
00166                 int width = height * imgSize.width() / imgSize.height();
00167                 scaledSize = QSize(width, height);
00168                 pos = QPoint((m_request.size.width() - scaledSize.width()) / 2,
00169                              (m_request.size.height() - scaledSize.height()) / 2);
00170             }
00171 
00172             break;
00173         case Wallpaper::MaxpectResize: {
00174             float xratio = (float) m_request.size.width() / imgSize.width();
00175             float yratio = (float) m_request.size.height() / imgSize.height();
00176             if (xratio > yratio) {
00177                 int height = m_request.size.height();
00178                 int width = height * imgSize.width() / imgSize.height();
00179                 scaledSize = QSize(width, height);
00180             } else {
00181                 int width = m_request.size.width();
00182                 int height = width * imgSize.height() / imgSize.width();
00183                 scaledSize = QSize(width, height);
00184             }
00185             pos = QPoint((m_request.size.width() - scaledSize.width()) / 2,
00186                          (m_request.size.height() - scaledSize.height()) / 2);
00187             break;
00188         }
00189         case Wallpaper::ScaledAndCroppedResize: {
00190             float xratio = (float) m_request.size.width() / imgSize.width();
00191             float yratio = (float) m_request.size.height() / imgSize.height();
00192             if (xratio > yratio) {
00193                 int width = m_request.size.width();
00194                 int height = width * imgSize.height() / imgSize.width();
00195                 scaledSize = QSize(width, height);
00196             } else {
00197                 int height = m_request.size.height();
00198                 int width = height * imgSize.width() / imgSize.height();
00199                 scaledSize = QSize(width, height);
00200             }
00201             pos = QPoint((m_request.size.width() - scaledSize.width()) / 2,
00202                          (m_request.size.height() - scaledSize.height()) / 2);
00203             break;
00204         }
00205         case Wallpaper::TiledResize:
00206             scaledSize = imgSize;
00207             tiled = true;
00208             break;
00209         case Wallpaper::CenterTiledResize:
00210             scaledSize = imgSize;
00211             pos = QPoint(-scaledSize.width() + ((m_request.size.width() - scaledSize.width()) / 2) % scaledSize.width(),
00212                          -scaledSize.height() + ((m_request.size.height() - scaledSize.height()) / 2) % scaledSize.height());
00213             tiled = true;
00214             break;
00215     }
00216 
00217     QPainter p(&result);
00218     //kDebug() << token << scalable << scaledSize << imgSize;
00219     if (scalable) {
00220         // tiling is ignored for scalable wallpapers
00221         QSvgRenderer svg(m_request.file);
00222         if (m_abort) {
00223             deleteLater();
00224         kDebug() << "oh, fuck it 2";
00225             return;
00226         }
00227         svg.render(&p);
00228     } else {
00229         if (scaledSize != imgSize) {
00230             img = img.scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
00231         }
00232 
00233         if (m_abort) {
00234             deleteLater();
00235         kDebug() << "oh, fuck it 3";
00236             return;
00237         }
00238 
00239         if (tiled) {
00240             for (int x = pos.x(); x < m_request.size.width(); x += scaledSize.width()) {
00241                 for (int y = pos.y(); y < m_request.size.height(); y += scaledSize.height()) {
00242                     p.drawImage(QPoint(x, y), img);
00243                     if (m_abort) {
00244         kDebug() << "oh, fuck it 4";
00245                         deleteLater();
00246                         return;
00247                     }
00248                 }
00249             }
00250         } else {
00251             p.drawImage(pos, img);
00252         }
00253     }
00254 
00255     // signal we're done
00256     if (!m_abort) {
00257         kDebug() << "*****************************************************";
00258         emit done(m_request, result);
00259     }
00260 
00261     deleteLater();
00262 }
00263 
00264 } // namespace Plasma
00265 
00266 #include "wallpaperrenderthread_p.moc"
00267 

Plasma

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal