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 <QPainter>
00024 #include <QFile>
00025 #include <QSvgRenderer>
00026
00027 #include <kdebug.h>
00028
00029 namespace Plasma
00030 {
00031
00032 WallpaperRenderThread::WallpaperRenderThread(QObject *parent)
00033 : QThread(parent),
00034 m_currentToken(-1)
00035 {
00036 m_abort = false;
00037 m_restart = false;
00038 }
00039
00040 WallpaperRenderThread::~WallpaperRenderThread()
00041 {
00042 {
00043
00044 QMutexLocker lock(&m_mutex);
00045 m_abort = true;
00046 m_condition.wakeOne();
00047 }
00048
00049 wait();
00050 }
00051
00052 void WallpaperRenderThread::setSize(const QSize& size)
00053 {
00054 QMutexLocker lock(&m_mutex);
00055 m_size = size;
00056 }
00057
00058 int WallpaperRenderThread::render(const QString &file,
00059 const QSize &size,
00060 Wallpaper::ResizeMethod method,
00061 const QColor &color)
00062 {
00063 int token;
00064 {
00065 QMutexLocker lock(&m_mutex);
00066 m_file = file;
00067 m_color = color;
00068 m_method = method;
00069 m_size = size;
00070 m_restart = true;
00071 token = ++m_currentToken;
00072 }
00073
00074 if (!isRunning()) {
00075 start();
00076 } else {
00077 m_condition.wakeOne();
00078 }
00079
00080 return token;
00081 }
00082
00083 void WallpaperRenderThread::run()
00084 {
00085 QString file;
00086 QColor color;
00087 QSize size;
00088 qreal ratio;
00089 Wallpaper::ResizeMethod method;
00090 int token;
00091
00092 forever {
00093 {
00094 QMutexLocker lock(&m_mutex);
00095
00096 while (!m_restart && !m_abort) {
00097 m_condition.wait(&m_mutex);
00098 }
00099
00100 if (m_abort) {
00101 return;
00102 }
00103
00104 m_restart = false;
00105
00106
00107 token = m_currentToken;
00108 file = m_file;
00109 color = m_color;
00110 size = m_size;
00111 ratio = m_size.width() / qreal(m_size.height());
00112 method = m_method;
00113 }
00114
00115 QImage result(size, QImage::Format_ARGB32_Premultiplied);
00116 result.fill(color.rgba());
00117
00118 if (file.isEmpty() || !QFile::exists(file)) {
00119 emit done(token, result, file, size, method, color);
00120 break;
00121 }
00122
00123 QPoint pos(0, 0);
00124 bool tiled = false;
00125 bool scalable = file.endsWith("svg") || file.endsWith("svgz");
00126 QSize scaledSize;
00127 QImage img;
00128
00129
00130 QSize imgSize;
00131 if (scalable) {
00132
00133 imgSize = size;
00134 } else {
00135
00136 img = QImage(file);
00137 imgSize = img.size();
00138
00139 }
00140
00141
00142 if (imgSize.width() < 1) {
00143 imgSize.setWidth(1);
00144 }
00145
00146 if (imgSize.height() < 1) {
00147 imgSize.setHeight(1);
00148 }
00149
00150 if (ratio < 1) {
00151 ratio = 1;
00152 }
00153
00154
00155 switch (method)
00156 {
00157 case Wallpaper::ScaledResize:
00158 imgSize *= ratio;
00159 scaledSize = size;
00160 break;
00161 case Wallpaper::CenteredResize:
00162 scaledSize = imgSize;
00163 pos = QPoint((size.width() - scaledSize.width()) / 2,
00164 (size.height() - scaledSize.height()) / 2);
00165
00166
00167 if (size.width() < imgSize.width() && imgSize.width() > imgSize.height()) {
00168 int width = size.width();
00169 int height = width * scaledSize.height() / imgSize.width();
00170 scaledSize = QSize(width, height);
00171 pos = QPoint((size.width() - scaledSize.width()) / 2,
00172 (size.height() - scaledSize.height()) / 2);
00173 } else if (size.height() < imgSize.height()) {
00174 int height = size.height();
00175 int width = height * imgSize.width() / imgSize.height();
00176 scaledSize = QSize(width, height);
00177 pos = QPoint((size.width() - scaledSize.width()) / 2,
00178 (size.height() - scaledSize.height()) / 2);
00179 }
00180
00181 break;
00182 case Wallpaper::MaxpectResize: {
00183 imgSize *= ratio;
00184 float xratio = (float) size.width() / imgSize.width();
00185 float yratio = (float) size.height() / imgSize.height();
00186 if (xratio > yratio) {
00187 int height = size.height();
00188 int width = height * imgSize.width() / imgSize.height();
00189 scaledSize = QSize(width, height);
00190 } else {
00191 int width = size.width();
00192 int height = width * imgSize.height() / imgSize.width();
00193 scaledSize = QSize(width, height);
00194 }
00195 pos = QPoint((size.width() - scaledSize.width()) / 2,
00196 (size.height() - scaledSize.height()) / 2);
00197 break;
00198 }
00199 case Wallpaper::ScaledAndCroppedResize: {
00200 imgSize *= ratio;
00201 float xratio = (float) size.width() / imgSize.width();
00202 float yratio = (float) size.height() / imgSize.height();
00203 if (xratio > yratio) {
00204 int width = size.width();
00205 int height = width * imgSize.height() / imgSize.width();
00206 scaledSize = QSize(width, height);
00207 } else {
00208 int height = size.height();
00209 int width = height * imgSize.width() / imgSize.height();
00210 scaledSize = QSize(width, height);
00211 }
00212 pos = QPoint((size.width() - scaledSize.width()) / 2,
00213 (size.height() - scaledSize.height()) / 2);
00214 break;
00215 }
00216 case Wallpaper::TiledResize:
00217 scaledSize = imgSize;
00218 tiled = true;
00219 break;
00220 case Wallpaper::CenterTiledResize:
00221 scaledSize = imgSize;
00222 pos = QPoint(
00223 -scaledSize.width() +
00224 ((size.width() - scaledSize.width()) / 2) % scaledSize.width(),
00225 -scaledSize.height() +
00226 ((size.height() - scaledSize.height()) / 2) % scaledSize.height());
00227 tiled = true;
00228 break;
00229 }
00230
00231 QPainter p(&result);
00232
00233 if (scalable) {
00234
00235 QSvgRenderer svg(file);
00236 if (m_restart) {
00237 continue;
00238 }
00239 svg.render(&p);
00240 } else {
00241 if (scaledSize != imgSize) {
00242 img = img.scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
00243 }
00244
00245 if (m_restart) {
00246 continue;
00247 }
00248
00249 if (tiled) {
00250 for (int x = pos.x(); x < size.width(); x += scaledSize.width()) {
00251 for (int y = pos.y(); y < size.height(); y += scaledSize.height()) {
00252 p.drawImage(QPoint(x, y), img);
00253 if (m_restart) {
00254 continue;
00255 }
00256 }
00257 }
00258 } else {
00259 p.drawImage(pos, img);
00260 }
00261 }
00262
00263
00264 emit done(token, result, file, size, method, color);
00265 break;
00266 }
00267 }
00268
00269 }
00270
00271 #include "wallpaperrenderthread_p.moc"
00272