Plasma
wallpaperrenderthread.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
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
00135 QSize imgSize(1, 1);
00136 if (scalable) {
00137
00138 imgSize = imgSize.expandedTo(m_request.size);
00139 } else {
00140
00141 img = QImage(m_request.file);
00142 imgSize = imgSize.expandedTo(img.size());
00143
00144 }
00145
00146
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
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
00219 if (scalable) {
00220
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
00256 if (!m_abort) {
00257 kDebug() << "*****************************************************";
00258 emit done(m_request, result);
00259 }
00260
00261 deleteLater();
00262 }
00263
00264 }
00265
00266 #include "wallpaperrenderthread_p.moc"
00267